Describe the bug
az advisor recommendation list retrieves the first page of Advisor recommendations, then follows the nextLink the service returns. On affected subscriptions, following that service-generated nextLink returns HTTP 404 with a non-JSON text/html body:
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
That message is the standard IIS/gateway response for a request URL that exceeds the URL-length limit. In our failing call the follow-up request path is 9,483 characters long, of which the $skiptoken alone is 9,332 characters — well over the usual ~8,192-byte (8 KB) URL limit. The first page succeeds (HTTP 200); only the follow-up to the nextLink fails.
Because the error body is not JSON, azure.core cannot map it to a ResourceNotFoundError with a structured payload and the command exits with code 3.
This is service-side, not a CLI defect per se — it reproduces via raw REST (az rest) with no SDK pagination logic — but it makes az advisor recommendation list unusable on affected subscriptions, so we are reporting it here for routing to the Advisor service team.
This is a regression with a clear onset: it started on 2026-07-14. The same command, on the same subscriptions, with the same read-only permissions and unchanged client (CLI/SDK), worked until then and began returning 404 on the nextLink from that date. Nothing changed on our side, which points to a service-side change rolled out around 2026-07-14.
The endpoint pages at 50 items per page. The first page returns 200 with 50 items and a nextLink; following that nextLink is what 404s. This is deterministic - an affected subscription fails on every run, always at the first nextLink.
Crucially, this is not simply "subscriptions with more than one page". Other subscriptions that also paginate - first page 200, then a nextLink that returns 200 - complete successfully. The difference is purely the length of the service-generated $skiptoken:
| Subscription |
$skiptoken length |
Full nextLink URL length |
nextLink result |
| Working |
~360 characters |
~511 characters |
200 OK |
| Failing |
~9,332 characters |
~9,483 characters |
404 (text/html) |
Same endpoint, same api-version=2020-01-01, same read-only permissions. The failing subscription's $skiptoken is ~26x larger and pushes the request URL past the gateway's ~8 KB limit. So the trigger is the size/shape of the $skiptoken, which varies by subscription data, not the raw number of recommendations. The $skiptoken is server-generated and the page size is fixed at 50, so there is no client-side knob ($top, smaller page) to shrink the URL.
Scope: we hit this on 44 of 261 subscriptions across several tenants, all with identical read-only Advisor permissions - the working and failing subscriptions differ only in their data.
Related command
az advisor recommendation list
Errors
azure.core.exceptions.ResourceNotFoundError: Operation returned an invalid status 'Not Found'
Content: The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Issue script & Debug output
az advisor recommendation list --debug (sensitive values redacted: subscription ID, tenant/object IDs, auth, and the multi-KB $skiptoken value are elided; a full trace can be shared privately).
Page 1 — 200 OK, returns 50 items + a nextLink:
Request URL: 'https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/providers/Microsoft.Advisor/recommendations?api-version=2020-01-01'
Request method: 'GET'
Response status: 200
'Content-Length': '67577'
'Content-Type': 'application/json; charset=utf-8'
Page 2 — following the service-provided nextLink → 404, text/html:
GET /subscriptions/<SUBSCRIPTION_ID>/providers/Microsoft.Advisor/recommendations?api-version=2020-01-01&$top=50&$skiptoken=<~9.3 KB $skiptoken elided> HTTP/1.1 -> 404 103
Response status: 404
'Content-Length': '103'
'Content-Type': 'text/html'
'X-Cache': 'CONFIG_NOCACHE'
'x-ms-request-id': 'f3d3e688-3bab-469f-a035-699614493f42'
'x-ms-correlation-request-id': 'f3d3e688-3bab-469f-a035-699614493f42'
'x-ms-routing-request-id': 'SOUTHCENTRALUS:20260715T153606Z:f3d3e688-3bab-469f-a035-699614493f42'
'Date': 'Wed, 15 Jul 2026 15:36:06 GMT'
Response content:
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Traceback (the SDK pager raising while fetching the next page):
File ".../azure/core/paging.py", line 76, in __next__
self._response = self._get_next(self.continuation_token)
File ".../azure/mgmt/advisor/operations/_recommendations_operations.py", line 230, in get_next
map_error(status_code=response.status_code, response=response, error_map=error_map)
File ".../azure/core/exceptions.py", line 107, in map_error
raise error
azure.core.exceptions.ResourceNotFoundError: Operation returned an invalid status 'Not Found'
Measured lengths of the failing request (from the debug log):
- Full GET request path: 9,483 characters
$skiptoken value alone: 9,332 characters (this is what pushes the URL past the ~8 KB limit)
- First page returned the full 50 items plus this
nextLink; the 404 is on the follow-up, not the first call
Second, independent failing example (different subscription, different tenant/region, same behavior - confirms it is not a one-off):
# Page 1 -> 200, 50 items + nextLink ($top=50, ~9.3 KB $skiptoken)
GET /subscriptions/<SUBSCRIPTION_ID_2>/providers/Microsoft.Advisor/recommendations?api-version=2020-01-01 -> 200 (Content-Length 69439)
# Follow the nextLink verbatim -> 404 text/html
GET .../recommendations?api-version=2020-01-01&$top=50&$skiptoken=<~9.3 KB elided> -> 404 103
'x-ms-request-id': 'fa0ddebf-3fd3-41f5-b4e3-4136258af19b'
'x-ms-correlation-request-id': 'fa0ddebf-3fd3-41f5-b4e3-4136258af19b'
'x-ms-routing-request-id': 'SOUTHCENTRALUS:20260722T155201Z:fa0ddebf-3fd3-41f5-b4e3-4136258af19b'
'Date': 'Wed, 22 Jul 2026 15:52:01 GMT'
Expected behavior
az advisor recommendation list should return the complete set of Advisor
recommendations for the subscription. Following the service-provided nextLink
should return HTTP 200 with the next page, so the command can paginate to the
end instead of failing with HTTP 404 on the second request.
The service should not hand back a nextLink whose $skiptoken makes the
request URL exceed the gateway's URL-length limit (~8 KB). The continuation
token must stay within a length the same endpoint can accept — as it already
does for subscriptions with smaller tokens (which paginate successfully), and
as Azure Resource Graph does by carrying the continuation token in the POST body.
Environment Summary
azure-cli 2.38.2
SDK: azsdk-python-mgmt-advisor/9.0.0
api-version: 2020-01-01
Python 3.9.25
OS: Linux (Amazon Linux 2023)
Also reproduced on the latest Azure CLI - identical 404 on the nextLink:
azure-cli 2.88.0
azure-cli-core 2.88.0
azure-cli-telemetry 1.1.0
So this is not a stale-CLI artifact; the initial report above is on 2.38.2 and it reproduces unchanged on 2.88.0.
Additional context
-
Reproduces via raw REST, independent of the CLI/SDK pagination code — confirming the defect is server-side:
# Page 1 returns a nextLink whose $skiptoken makes the follow-up URL exceed ~8 KB.
NL=$(az rest --method get \
--url "https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/providers/Microsoft.Advisor/recommendations?api-version=2020-01-01" \
--query nextLink -o tsv)
echo "nextLink length: ${#NL}" # ~9,500 characters
# Following the service-provided nextLink verbatim:
az rest --method get --url "$NL" --debug 2>&1 | grep "Response status" # -> 404
-
The 404 body is Content-Type: text/html, Content-Length: 103 — the IIS "resource not found" page, which is what a gateway returns when the request URL exceeds its maximum length. This points to the URL-embedded $skiptoken length as the root cause, not a missing resource.
-
The failure tracks $skiptoken size, not result volume. Across one collection run over many subscriptions, subscriptions that paginate across several successful nextLink hops (larger recommendation sets) completed fine, while others failed on the first nextLink. The failing and working subscriptions share the same tenant/region and identical read-only permissions - they differ only in the data that shapes the $skiptoken.
-
Azure Resource Graph returns the full set reliably for the same subscriptions, e.g. advisorresources | where type =~ 'microsoft.advisor/recommendations' — because its continuation token travels in the POST body rather than in the URL. Strong corroboration that the defect is the URL-embedded $skiptoken growing past the URL-length limit on the recommendations LIST endpoint.
-
Regression onset 2026-07-14: the affected subscriptions returned full results before that date and started 404-ing on the nextLink from then on, with no client-side change - suggests the $skiptoken format/size changed in a service rollout around 2026-07-14. Correlating against that deployment is likely the fastest path to root cause.
-
Suggested fixes for the service team: cap/compact the $skiptoken so the resulting nextLink stays within the gateway URL limit, or return a token that can be sent in a header/body.
-
Correlation/request IDs, timestamps, and routing regions for two independent failing calls are included above; more can be shared privately for tracing.
-
Secondary CLI/SDK note (not the root cause): when the service returns a non-JSON error body, the client surfaces a bare ResourceNotFoundError with the raw HTML. Detecting a non-JSON error body and reporting the likely URL-length cause would make this much easier to diagnose.
Describe the bug
az advisor recommendation listretrieves the first page of Advisor recommendations, then follows thenextLinkthe service returns. On affected subscriptions, following that service-generatednextLinkreturns HTTP 404 with a non-JSONtext/htmlbody:That message is the standard IIS/gateway response for a request URL that exceeds the URL-length limit. In our failing call the follow-up request path is 9,483 characters long, of which the
$skiptokenalone is 9,332 characters — well over the usual ~8,192-byte (8 KB) URL limit. The first page succeeds (HTTP 200); only the follow-up to thenextLinkfails.Because the error body is not JSON,
azure.corecannot map it to aResourceNotFoundErrorwith a structured payload and the command exits with code 3.This is service-side, not a CLI defect per se — it reproduces via raw REST (
az rest) with no SDK pagination logic — but it makesaz advisor recommendation listunusable on affected subscriptions, so we are reporting it here for routing to the Advisor service team.This is a regression with a clear onset: it started on 2026-07-14. The same command, on the same subscriptions, with the same read-only permissions and unchanged client (CLI/SDK), worked until then and began returning 404 on the
nextLinkfrom that date. Nothing changed on our side, which points to a service-side change rolled out around 2026-07-14.The endpoint pages at 50 items per page. The first page returns 200 with 50 items and a
nextLink; following thatnextLinkis what 404s. This is deterministic - an affected subscription fails on every run, always at the firstnextLink.Crucially, this is not simply "subscriptions with more than one page". Other subscriptions that also paginate - first page 200, then a
nextLinkthat returns 200 - complete successfully. The difference is purely the length of the service-generated$skiptoken:$skiptokenlengthnextLinkURL lengthnextLinkresultSame endpoint, same
api-version=2020-01-01, same read-only permissions. The failing subscription's$skiptokenis ~26x larger and pushes the request URL past the gateway's ~8 KB limit. So the trigger is the size/shape of the$skiptoken, which varies by subscription data, not the raw number of recommendations. The$skiptokenis server-generated and the page size is fixed at 50, so there is no client-side knob ($top, smaller page) to shrink the URL.Scope: we hit this on 44 of 261 subscriptions across several tenants, all with identical read-only Advisor permissions - the working and failing subscriptions differ only in their data.
Related command
Errors
Issue script & Debug output
az advisor recommendation list --debug(sensitive values redacted: subscription ID, tenant/object IDs, auth, and the multi-KB$skiptokenvalue are elided; a full trace can be shared privately).Page 1 — 200 OK, returns 50 items + a
nextLink:Page 2 — following the service-provided
nextLink→ 404,text/html:Traceback (the SDK pager raising while fetching the next page):
Measured lengths of the failing request (from the debug log):
$skiptokenvalue alone: 9,332 characters (this is what pushes the URL past the ~8 KB limit)nextLink; the 404 is on the follow-up, not the first callSecond, independent failing example (different subscription, different tenant/region, same behavior - confirms it is not a one-off):
Expected behavior
az advisor recommendation listshould return the complete set of Advisorrecommendations for the subscription. Following the service-provided
nextLinkshould return HTTP 200 with the next page, so the command can paginate to the
end instead of failing with HTTP 404 on the second request.
The service should not hand back a
nextLinkwhose$skiptokenmakes therequest URL exceed the gateway's URL-length limit (~8 KB). The continuation
token must stay within a length the same endpoint can accept — as it already
does for subscriptions with smaller tokens (which paginate successfully), and
as Azure Resource Graph does by carrying the continuation token in the POST body.
Environment Summary
Also reproduced on the latest Azure CLI - identical 404 on the
nextLink:So this is not a stale-CLI artifact; the initial report above is on 2.38.2 and it reproduces unchanged on 2.88.0.
Additional context
Reproduces via raw REST, independent of the CLI/SDK pagination code — confirming the defect is server-side:
The 404 body is
Content-Type: text/html,Content-Length: 103— the IIS "resource not found" page, which is what a gateway returns when the request URL exceeds its maximum length. This points to the URL-embedded$skiptokenlength as the root cause, not a missing resource.The failure tracks
$skiptokensize, not result volume. Across one collection run over many subscriptions, subscriptions that paginate across several successfulnextLinkhops (larger recommendation sets) completed fine, while others failed on the firstnextLink. The failing and working subscriptions share the same tenant/region and identical read-only permissions - they differ only in the data that shapes the$skiptoken.Azure Resource Graph returns the full set reliably for the same subscriptions, e.g.
advisorresources | where type =~ 'microsoft.advisor/recommendations'— because its continuation token travels in the POST body rather than in the URL. Strong corroboration that the defect is the URL-embedded$skiptokengrowing past the URL-length limit on the recommendations LIST endpoint.Regression onset 2026-07-14: the affected subscriptions returned full results before that date and started 404-ing on the
nextLinkfrom then on, with no client-side change - suggests the$skiptokenformat/size changed in a service rollout around 2026-07-14. Correlating against that deployment is likely the fastest path to root cause.Suggested fixes for the service team: cap/compact the
$skiptokenso the resultingnextLinkstays within the gateway URL limit, or return a token that can be sent in a header/body.Correlation/request IDs, timestamps, and routing regions for two independent failing calls are included above; more can be shared privately for tracing.
Secondary CLI/SDK note (not the root cause): when the service returns a non-JSON error body, the client surfaces a bare
ResourceNotFoundErrorwith the raw HTML. Detecting a non-JSON error body and reporting the likely URL-length cause would make this much easier to diagnose.