Repository navigation
fix: make async scanner polling resilient to transient errors - #2307
Conversation
A single poll response with an error status ended the scan job, and a failed poll call could end the polling chain. Scans that Argus later completed were recorded as failed. - Poll requests now throw on any non-2xx response, so a 4xx error body is no longer read as a scan status. - A poll that throws is recorded and the next poll is scheduled, bounded by max-attempts. - An error status must be seen on two consecutive polls before the job fails. - The raw response is logged when a poll maps to FAILED. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Strict mode misses 3xx responses, and the internal failure marker leaks through the admin API.
2 open findings
What changed in this PR
Improves resilience of asynchronous scanner polling during transient failures.
Changes:
- Adds strict HTTP status handling for polling.
- Retries poll exceptions and confirms consecutive failure statuses.
- Adds regression tests for polling and HTTP behavior.
| File | Description |
|---|---|
ScannerPollHandler.java |
Reschedules failed polls and confirms scanner failures. |
RemoteScanner.java |
Uses strict polling requests and logs failed responses. |
HttpClientExecutor.java |
Adds configurable strict response handling. |
ScannerPollHandlerTest.java |
Tests polling recovery and failure confirmation. |
HttpClientExecutorTest.java |
Tests strict and lenient 4xx handling. |
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
- Strict HTTP execution now rejects 3xx responses, which RestTemplate does not throw for. - The admin API only exposes a scanner job's error message once the job is terminal, so transient poll errors on active jobs are not shown. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
The previously identified issues are resolved with focused regression coverage.
0 open findings
2 resolved since last review
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
The 4xx pass-through is no longer needed, so the strict mode added for polling is dropped and all scanner HTTP calls fail on non-2xx. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Redirect-following remains enabled, allowing some 3xx scanner responses to bypass the new validation.
1 open finding
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
The changes address the reported failure modes with focused regression coverage and no unresolved issues.
0 open findings
1 resolved since last review
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Problem
Some Argus scans were recorded as
External scan failed (no details from scanner)although Argus completed them successfully. Two causes in the poll path:status: error(mapped toFAILED) was terminal. A scanner that reports a transient error and then recovers still failed the scan.HttpClientExecutorreturns the body of any 4xx response as a success, so a 4xx JSON error body could be read as a scan status.The "no details" text comes from
fetchErrorDetailcalling the result endpoint, which is the same URL as poll and returns a body with no matches.Changes
HttpClientExecutor: every non-2xx response (including 3xx) is an error, for start, poll and result calls. The 4xx body pass-through is removed, since it is no longer needed and let an error body be read as a scan status.ScannerPollHandler: aScannerExceptionduring polling is recorded on the job and the next poll is scheduled. It counts towardsmax-attempts.ScanAPI: a scanner job exposeserrorMessageonly once terminal, so the transient marker is not shown.ScannerPollHandler:FAILEDmust be seen on two consecutive polls before the job fails. The first sighting is stored as a marker inScannerJob.errorMessage, which avoids a schema change. Any other status clears it.RemoteScanner: the truncated raw response is logged at WARN when a poll maps toFAILED.Tests
ScannerPollHandlerTest: first error not final, second consecutive error final, recovery clears the marker, poll exception reschedules.HttpClientExecutorTest: 4xx and 3xx responses with a body throw../gradlew test --tests 'org.eclipse.openvsx.scanning.*'passes except 4 recovery-lock tests that need Testcontainers, which could not start here.spotlessCheckis clean.Notes
A real failure is now detected one poll interval later (15s for Argus).
🤖 Generated with Claude Code