Skip to content

Fix AndroidMessageHandler upload I/O exception translation - #13125

Open
simonrozsival wants to merge 2 commits into
mainfrom
simonrozsival-android-upload-exceptions
Open

simonrozsival wants to merge 2 commits into
mainfrom
simonrozsival-android-upload-exceptions

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Fixes #12934's upload exception-contract failure. The TLS performance concern remains separate; measurements are attached to the issue. This PR makes no TLS or default-handler changes.

OutputStreamInvoker wraps Java transport failures in managed IOException, bypassing the handler's Java-only exception translation. Translate managed I/O failures during request-body copying using the existing compatibility helper. Cancellation handling runs first, the original exception chain is retained, seekable streams are rewound, and unrelated application exceptions remain unchanged.

Adds repeated loopback upload-reset coverage for both completion options, asserting the exception chain, uncancelled caller token, and rewind. Also tests content-source I/O/non-I/O failures and enables focused execution of existing connection/redirect tests.

Validation

Release, physical Samsung SM-A165F, API 36, arm64. Current checkout targets net11.0-android but pins runtime 12.0.0-alpha.1.26509.101; the reporter's exact .NET 11 RC package and x86_64/Mono/NativeAOT configurations were not tested.

  • make prepare CONFIGURATION=Release && make all CONFIGURATION=Release — preparation passed; initial build failed on missing extra API reference assemblies.
  • ./dotnet-local.sh build Microsoft.Android.slnx -c Release -t:BuildExtraApiLevels -v:q — passed; subsequent make all CONFIGURATION=Release passed.
  • ./dotnet-local.sh build -t:ConfigureLocalWorkload -c Release build-tools/create-packs/Microsoft.Android.Sdk.proj -v:q — passed.
  • Final make all CONFIGURATION=Release — passed, 0 warnings/errors.
  • git diff --check — passed.

Final install — passed, 0 errors, 38 existing analysis/trimming warnings:

ANDROID_SERIAL=R58Y30HZ65V ./dotnet-local.sh build -t:Install -c Release \
  -p:RuntimeIdentifier=android-arm64 '-p:AdbTarget=-s R58Y30HZ65V' \
  '-p:IncludeCategories=AndroidMessageHandlerExceptions%3BAndroidMessageHandlerCancellation' \
  tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -v:q

Final device run — 16 passed, 0 failed, 0 skipped:

(cd tests/Mono.Android-Tests/Mono.Android-Tests && \
  ANDROID_SERIAL=R58Y30HZ65V ../../../dotnet-local.sh test Mono.Android.NET-Tests.csproj \
  --no-build -c Release -p:RuntimeIdentifier=android-arm64 \
  '-p:IncludeCategories=AndroidMessageHandlerExceptions%3BAndroidMessageHandlerCancellation' \
  --device R58Y30HZ65V --report-trx \
  --results-directory ../../../bin/TestRelease/TestResults)

Before/after proof: temporarily removing only the production catch, rebuilding, and running the upload category produced 3 failures in 4 cases: both resets and source IOException failed; unrelated application-exception propagation passed. Restoring the catch and rebuilding produced the passing final run. NUnit counts each three-repeat reset as one case.

Preserve cancellation and the legacy WebException exception chain. Add repeated loopback upload-reset and content-source failure coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 13, 2026 15:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation and regression coverage are sound; only a non-blocking namespace convention suggestion remains.

1 open finding
What changed in this PR

Fixes upload I/O exception translation in AndroidMessageHandler, aligning failures with the HttpClient contract.

Changes:

  • Translates managed upload IOException failures into HttpRequestException.
  • Adds loopback regression coverage for resets, exception chains, cancellation, and stream rewind.
  • Adds focused exception-test categories.
File Description
AndroidMessageHandler.cs Translates upload I/O failures.
AndroidMessageHandlerUploadTests.cs Adds upload failure regression tests.
AndroidMessageHandlerTests.cs Categorizes existing exception tests.
Mono.Android.NET-Tests.csproj Includes the new test file.

🧠 Review effort: Balanced

@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

✅ Android PR Reviewer completed successfully!

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • azcliprod.blob.core.windows.net

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "azcliprod.blob.core.windows.net"

See Network Configuration for more information.

Generated by Android PR Reviewer for #13125

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

Verdict: ❌ Reject — 1 error, 0 warnings, 0 suggestions

The new catch correctly translates copy-time managed I/O failures while preserving cancellation precedence and the compatibility WebException chain. However, the equivalent I/O failure path from HttpContent.ReadAsStreamAsync() remains outside the translation boundary, so the SendAsync exception contract is still incomplete; details and a regression-test request are inline.

CI was still in progress when reviewed: 38 of 42 checks had completed successfully, with three emulator lanes running and the aggregate check queued; no failures were reported.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • azcliprod.blob.core.windows.net

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "azcliprod.blob.core.windows.net"

See Network Configuration for more information.

Generated by Android PR Reviewer for #13125 · copilot · gpt56 · 108.4 AIC · ⌖ 11.2 AIC · ⊞ 26.4K
Comment /review to run again

Comment thread src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
Include ReadAsStreamAsync in the existing cancellation and I/O exception translation boundary, and only rewind an acquired stream. Exercise acquisition and copy failures, application exceptions, cancellation precedence, and rewind in regression tests. Use a file-scoped namespace for the new fixture.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[.NET 11] AndroidMessageHandler still throws IOException during upload

2 participants