Skip to content

Decode escaped error messages in check_success - #5364

Merged
Heath Stewart (heaths) merged 3 commits into
Azure:mainfrom
aelmanaa:fix/error-response-escaped-message
Sep 29, 2026
Merged

Heath Stewart (heaths) merged 3 commits into
Azure:mainfrom
aelmanaa:fix/error-response-escaped-message

Conversation

@aelmanaa

Copy link
Copy Markdown
Contributor

Fixes #5363

check_success parses the service error body into ErrorResponseInternal, whose code and message fields were borrowed as &str. serde_json cannot borrow a string that contains JSON escape sequences, so any error message with an escape (Key Vault RBAC errors always contain \r\n) failed to parse, and the error fell back to "{status}: {raw body}" with the status text as the error code.

This changes those two fields to owned Strings. The public ErrorResponse / ErrorDetail types already use owned strings and parse these bodies correctly; the change only affects the error path, so the extra allocation is limited to failed requests. (#[serde(borrow)] on Option<Cow<str>> would not avoid it either, since serde does not borrow through Option.)

Tests: deserialize_to_error_response_internal_with_escapes and matching_against_http_error_with_escaped_message fail on main and pass with this change; the rest of azure_core tests, cargo clippy --all-targets --all-features -- -D warnings, and cargo fmt --check pass. No public API changes, so no CHANGELOG entry per the changelog instructions.

This was found while building an Azure Key Vault Ethereum signer on top of azure_security_keyvault_keys. The change was written with Claude Code; I reviewed and tested it.

@github-actions github-actions Bot added Azure.Core The azure_core crate Community Contribution Community members are working on the issue customer-reported Issues that are reported by GitHub users external to the Azure organization. labels Sep 28, 2026
@github-actions

Copy link
Copy Markdown

Thank you for your contribution Amine E. (@aelmanaa)! We will review the pull request and get back to you soon.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@aelmanaa

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

Comment thread sdk/core/azure_core/src/error/error_response.rs
@heaths

Copy link
Copy Markdown
Member

Amine E. (@aelmanaa) thanks for your contribution! I want to get a couple other opinions since I may be over-optimizing here. If the message weren't invariably owned—ignoring any short circuit returns from parsing errors, etc.—it'd be worth it. Some services may return very large messages from experience. But since only code may possibly be borrowed it's probably not worth it. This may be useful elsewhere, however, but we also probably don't need it right now.

@aelmanaa

Copy link
Copy Markdown
Contributor Author

Heath Stewart (@heaths) thanks for taking this further, and for the custom deserializer; borrowing code while owning message makes sense to me.

FYI to save you some digging on the red CI: the only failure is cargo test --benches in http_transport_benchmarks (benches/http_transport_benchmarks.rs:47, assertion failed: response.is_ok()), on the Linux and Windows jobs (it's skipped on macOS). That benchmark calls the live HTTP_ENDPOINT from azure_core_examples (https://azuresdkforcpp.azurewebsites.net), which currently doesn't resolve in DNS, so the requests fail regardless of this change. The azure_core unit tests (110) pass in those same jobs and locally on your commit.

@aelmanaa

Copy link
Copy Markdown
Contributor Author

Follow-up: I confirmed this locally on your commit (1c8534e). azuresdkforcpp.azurewebsites.net returns NXDOMAIN from public resolvers (8.8.8.8, 1.1.1.1), and in all five red jobs http_transport_benchmarks is the only failed target. With the benchmark pointed at https://httpbin.org instead (and the macOS skip removed, locally only), all four transport benchmarks pass, and cargo test --benches -p azure_core --all-features passes. So re-pointing HTTP_ENDPOINT in azure_core_examples (or restoring that site) should turn CI green.

@heaths

Copy link
Copy Markdown
Member

This is fixed in another PR: #5371. Rebasing should resolve it, but hold off on any further changes until we decide to take my changes or not. At the very least we'll need the CHANGELOG.md change.

Amine E. (aelmanaa) and others added 3 commits September 29, 2026 14:23
`ErrorDetailsInternal` borrowed `code` and `message` as `&str`, which
serde_json cannot do when the JSON string contains escape sequences.
Messages such as Key Vault's RBAC errors, which contain `\r\n`, then failed
to parse and the error fell back to the raw response body. Use owned strings
so the service message and code are extracted.

Fixes Azure#5363

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
We may not need to allocate for the custom error code.
@heaths
Heath Stewart (heaths) force-pushed the fix/error-response-escaped-message branch from 1c8534e to a7fcc90 Compare September 29, 2026 21:41
@heaths

Copy link
Copy Markdown
Member

Talked to Larry Osterman (@LarryOsterman) offline who agrees this is over-optimizing. I couldn't really figure out a way to make it worth it for message because we inevitably and unconditionally—at least from the point we deserialize the error response body—end up allocating a new String for message anyway even if we pass a Cow<'_, str> to Error::with_message(). Reverted, but left the CHANGELOG.md change in.

@heaths
Heath Stewart (heaths) merged commit 7ba99b4 into Azure:main Sep 29, 2026
15 checks passed
@aelmanaa

Copy link
Copy Markdown
Contributor Author

Heath Stewart (@heaths) thanks for merging! Two small things in the CHANGELOG.md line, in case they're useful when you open the next section:

  • It landed under ## 1.2.0-beta.1 (2026-09-04), which was already published on Sept 5, because the post-release version bump (like Update core package versions and fix dependencies #4744 after 1.1.0) hasn't happened yet. So it will need to move to the next unreleased section.
  • It says check_status, but the function is check_success.

@heaths

Copy link
Copy Markdown
Member

Amine E. (@aelmanaa) thanks for noticing. I didn't realize we hadn't yet merged #5257 and am prepping that now. I'll pick up these changes there.

Heath Stewart (heaths) added a commit that referenced this pull request Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Azure.Core The azure_core crate Community Contribution Community members are working on the issue customer-reported Issues that are reported by GitHub users external to the Azure organization.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

azure_core: error message falls back to raw response body when the service message contains JSON escapes

3 participants