Certificate Wizard: show the real signing error instead of a blanket HTTP 502 - #5567
Merged
Conversation
"Sync with Apple" reported every server-side failure as "Codename One cloud signing service failed (HTTP 502). Try again later." CloudSigningService.message() short-circuited on `code >= 500` and threw the response body away -- so when the cloud service explained that the account's App Store Connect API key had been revoked, the developer was told to wait it out instead. The generated REST client already hands the callback the raw body on an error status (the onErrorCodeString handler it emits), so the body was there the whole time. SigningError now reads it for every status and classifies the failure, and the banner renders what the service said. Bodies are not trusted blindly: a proxy or CDN in front of the service answers 5xx with its own HTML page or a stub like `error code: 522`, so a 5xx body has to look like prose before it reaches the UI, and anything HTML-ish, JSON-ish or overlong falls back to a written message. The banner grew a next step to go with the sentence -- "Open ASC API Key" for a credential problem, "Try again" for something genuinely transient -- and became a SpanLabel, because a Label clipped these messages to one line. It stays selectable so the text can be copied into a support thread. Specs track the server: NotConfigured becomes AscKeyProblem, and the Apple-calling paths document 422/429/404 alongside 502. openapi.json is regenerated from the yaml. Tests: SigningErrorTest pins the mapping (including the CDN and HTML cases); CertificateWizardErrorBannerTest drives the real "Sync with Apple" button and asserts what lands on screen and where the buttons go. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
App Groups load as the last of the seven calls a refresh chains together, and any failure there discarded the six that had already succeeded and reported an error instead. Apple answers `GET /v1/appGroups` with 404 "The path provided does not match a defined resource type" for accounts it does not offer the resource to, so those developers got an error on every refresh -- and because a successful "Sync with Apple" ends in a refresh, a sync that had worked perfectly reported "cloud signing service failed (HTTP 502). Try again later." By the time this call runs, the six before it have proved both the Codename One login and the Apple key are good, so treating a failure here as "no App Groups" gives up nothing: the developer keeps their certificates, bundle IDs, devices, profiles and APNs keys on screen. The server no longer raises this at all, but the wizard should not have been this brittle either -- and a released wizard gets the fix without waiting for a deploy. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
check-copyright-headers validates every file a PR adds *or modifies*, and the three files in certificatewizard/api had no header: SigningError.java is new and I wrote it without one, while CloudSigningService.java and SigningService.java predate this branch and were only caught because these changes touch them. Header copied verbatim from CertificateWizard.java in the same module. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A customer reported that for 24 hours, clicking Sync with Apple returned:
Their App Store Connect key was fine. So was the sync — it had already succeeded.
What was happening
Production logs show Apple answering one call with a 404:
That is Apple saying the path is not a resource type it knows — App Store Connect does not offer App Groups to that account. (A collection that exists but is empty answers 200 with an empty
dataarray.)CloudSigningService.refresh()chains seven calls and loads App Groups last, and any failure there discarded the six that had already succeeded.afterMutationcallsreload()on success, so the reconcile completed, the follow-up refresh died on call seven, and the developer was told to wait out something that had worked.Two things then made it unreadable: the cloud service reported every Apple failure as
502, andCloudSigningService.message()short-circuited oncode >= 500and threw the response body away.Changes
8635e0f09a— surface what the service actually said. The generated REST client already hands the callback the raw body on an error status (via theonErrorCodeStringhandler it emits), so the explanation was there all along.SigningErrornow reads it for every status and classifies the failure; the banner renders it with a next step attached — "Open ASC API Key" for a credential problem, "Try again" for something genuinely transient.Bodies are not trusted blindly: a proxy or CDN in front of the service answers 5xx with its own HTML page or a stub like
error code: 522, so a 5xx body has to read like prose before it reaches the UI. The banner became aSpanLabelbecause aLabelclipped these messages to one line, and it stays selectable so the text can be pasted into a support thread.7e432be24d— stop one optional call from discarding the account. By the time App Groups load, the six calls before them have proved both the Codename One login and the Apple key are good, so a failure there is treated as "no App Groups". The developer keeps their certificates, bundle IDs, devices, profiles and APNs keys on screen.Specs track the server contract:
NotConfiguredbecomesAscKeyProblem, and the Apple-calling paths document 422/429/404 alongside 502.openapi.jsonis regenerated from the yaml it is derived from.Tests
38/38 green (
mvn -B test), including:SigningErrorTest— the status→message mapping, including the CDN-stub and HTML-error-page cases that must never reach the UI.CertificateWizardErrorBannerTest— drives the real Sync with Apple button and asserts what lands on screen, that the old catch-all string is gone, and that the credential action navigates to the ASC API Key page.Related
Server side is BuildCloud #130, which fixes the root cause (
listAppGroupsreads the 404 as "no App Groups") and stops flattening every Apple failure into a 502. Either side alone clears the customer's symptom: the server fix reaches everyone on a released wizard without a client update, and this one fixes a rebuilt wizard without waiting for a deploy.🤖 Generated with Claude Code