[GH-ISSUE #4517] [Bug]: App Registrations List Dropping Last Item #2075

Closed
opened 2026-03-02 13:49:25 +03:00 by kerem · 3 comments
Owner

Originally created by @Ben-ITLogic on GitHub (Aug 12, 2025).
Original GitHub issue: https://github.com/KelvinTegelaar/CIPP/issues/4517

Required confirmations before submitting

  • I can reproduce this issue on the latest released versions of both CIPP and CIPP-API.
  • I have searched existing issues (both open and closed) to avoid duplicates.
  • I am not requesting general support; this is an actual bug report.

Issue Description

  1. Navigate to > Tenant Administration > Applications > App Registrations.
  2. Count them.
  3. Navigate to Tools > Tenant Tools > Graph Explorer.
  4. Configure as per:
    Endpoint: applications
    Top: 999
    Use $count: On
  5. Click Apply Filter.
  6. Count them - There will always be one extra directly from Graph.

The graph explorer configuration matches the API calls made from the CIPP page data (to the best of my ability)

Environment Type

Non-sponsored user

Front End Version

v8.3.0

Back End Version

v8.3.0

Relevant Logs / Stack Trace


Originally created by @Ben-ITLogic on GitHub (Aug 12, 2025). Original GitHub issue: https://github.com/KelvinTegelaar/CIPP/issues/4517 ### Required confirmations before submitting - [x] **I can reproduce this issue on the latest released versions** of both CIPP and CIPP-API. - [x] **I have searched existing issues** (both open and closed) to avoid duplicates. - [x] I am **not** requesting general support; this is an actual bug report. ### Issue Description 1. Navigate to > Tenant Administration > Applications > App Registrations. 2. Count them. 3. Navigate to Tools > Tenant Tools > Graph Explorer. 4. Configure as per: Endpoint: applications Top: 999 Use $count: On 5. Click Apply Filter. 6. Count them - There will always be one extra directly from Graph. The graph explorer configuration matches the API calls made from the CIPP page data (to the best of my ability) ### Environment Type Non-sponsored user ### Front End Version v8.3.0 ### Back End Version v8.3.0 ### Relevant Logs / Stack Trace ```plaintext ```
Author
Owner

@github-actions[bot] commented on GitHub (Aug 12, 2025):

Thank you for reporting a potential bug. If you would like to work on this bug, please comment:

I would like to work on this please!

Thank you for helping us maintain the project!

<!-- gh-comment-id:3177554881 --> @github-actions[bot] commented on GitHub (Aug 12, 2025): Thank you for reporting a potential bug. If you would like to work on this bug, please comment: > I would like to work on this please! Thank you for helping us maintain the project!
Author
Owner

@Ben-ITLogic commented on GitHub (Aug 12, 2025):

Okay, I did a bit more digging.

The page calls:
/api/ListGraphRequest?tenantFilter=DOMAIN&Endpoint=applications&$count=true&$top=999

The Graph Explorer calls:
/api/ListGraphRequest?tenantFilter=DOMAIN&endpoint=applications&$filter=&$expand=&$top=&$search=&$format=&ReverseTenantLookupProperty=tenantId&manualPagination=false&IsShared=false&name=&AsApp=false

The issue seems to be manualPagination=.

If manualPagination=false OR manualPagination=true, the results return correctly.

<!-- gh-comment-id:3177583603 --> @Ben-ITLogic commented on GitHub (Aug 12, 2025): Okay, I did a bit more digging. The page calls: /api/ListGraphRequest?tenantFilter=DOMAIN&Endpoint=applications&$count=true&$top=999 The Graph Explorer calls: /api/ListGraphRequest?tenantFilter=DOMAIN&endpoint=applications&$filter=&$expand=&$top=&$search=&$format=&ReverseTenantLookupProperty=tenantId&manualPagination=false&IsShared=false&name=&AsApp=false The issue seems to be manualPagination=. If manualPagination=false OR manualPagination=true, the results return correctly.
Author
Owner

@nichxlxs commented on GitHub (Aug 12, 2025):

Invoke-ListGraphRequest unconditionally drops the last record to attempt to remove the nextLink element.

    try {
        $Results = Get-GraphRequestList @GraphRequestParams
        if ($Results.nextLink) {
            Write-Host "NextLink: $($Results.nextLink | Select-Object -Last 1)"
            if ($Request.Query.TenantFilter -ne 'AllTenants') {
                $Metadata['nextLink'] = $Results.nextLink | Select-Object -Last 1
            }
            #Results is an array of objects, so we need to remove the last object before returning
            $Results = $Results | Select-Object -First ($Results.Count - 1)
        }

There are two possibilities this can drop a real row:

  1. If the nextLink property is not at the end (e.g., it's in the middle of the array after being merged in Get-GraphRequestList).

  2. In a small dataset, there is no real nextLink, however, $Results.nextLink returns an array of values (often @($null,$null,...) when no element has a 'nextLink' property set). In PowerShell, a non-empty array of $null is evaluated as truthy in an if, even if every element is $null. The block will run even when there is no actual nextLink, causing the real item to be dropped anyway.

This only happens when the NoPagination/manualPagination parameters are not provided, because:

  • In Get-GraphRequestList, if .NoPagination.IsPresent is $true (either true or false), the $count branch is skipped, and New-GraphGetRequest is called in a mode that either:
    • Returns only data items (no nextLink property at all as single page), or
    • Returns data items with a { nextLink = … } object always as the last element – in this case dropping the last element is safe.

When .NoPagination is omitted, the $count branch runs, which can merge in a { nextLink = … } object in a non-last position or can also trigger the truthy condition above if there is a small data size.

Another thing to note is that this is the default behaviour in the “App Registrations” page, which automatically appends &$count=true&$top=999 to the query and does not set manualPagination. That means small result sets lose one record.

<!-- gh-comment-id:3177733615 --> @nichxlxs commented on GitHub (Aug 12, 2025): [Invoke-ListGraphRequest](https://github.com/KelvinTegelaar/CIPP-API/blob/master/Modules/CIPPCore/Public/Entrypoints/HTTP%20Functions/CIPP/Core/Invoke-ListGraphRequest.ps1) unconditionally drops the last record to attempt to remove the `nextLink` element. ```powershell try { $Results = Get-GraphRequestList @GraphRequestParams if ($Results.nextLink) { Write-Host "NextLink: $($Results.nextLink | Select-Object -Last 1)" if ($Request.Query.TenantFilter -ne 'AllTenants') { $Metadata['nextLink'] = $Results.nextLink | Select-Object -Last 1 } #Results is an array of objects, so we need to remove the last object before returning $Results = $Results | Select-Object -First ($Results.Count - 1) } ``` There are two possibilities this can drop a real row: 1. If the `nextLink` property is not at the end (e.g., it's in the middle of the array after being merged in `Get-GraphRequestList`). 2. In a small dataset, there is no real `nextLink`, however, `$Results.nextLink` returns an array of values (often `@($null,$null,...)` when no element has a 'nextLink' property set). In PowerShell, a non-empty array of `$null` is evaluated as truthy in an `if`, even if every element is `$null`. The block will run even when there is no actual `nextLink`, causing the real item to be dropped anyway. This only happens when the `NoPagination`/`manualPagination` parameters are not provided, because: - In `Get-GraphRequestList`, if `.NoPagination.IsPresent` is `$true` (either `true` or `false`), the `$count` branch is skipped, and `New-GraphGetRequest` is called in a mode that either: - Returns only data items (no `nextLink` property at all as single page), or - Returns data items with a `{ nextLink = … }` object always as the last element – in this case dropping the last element is safe. When `.NoPagination` is omitted, the `$count` branch runs, which can merge in a `{ nextLink = … }` object in a non-last position or can also trigger the truthy condition above if there is a small data size. Another thing to note is that this is the default behaviour in the “App Registrations” page, which automatically appends `&$count=true&$top=999` to the query and does not set `manualPagination`. That means small result sets lose one record.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/CIPP#2075
No description provided.