fix(webapp): show an error instead of silently resetting the new-organization form - #4530
fix(webapp): show an error instead of silently resetting the new-organization form#4530claude[bot] wants to merge 1 commit into
Conversation
|
Observability mapAs of 18/100 over 413 measured of 429 entry points (base 18, no change) What this PR changed
FIX FIRST
AUDIT 3 of 50 sensitive mutations record an actor. 47 without one. What the score is made ofThe score and findings here are report-only and never gate the merge. Separately, a required test suite keeps this tool's symbol and route lists in sync with the code they name, and can fail a pull request that renames or removes a symbol they reference, or that adds the first route with a segment they anticipate. Each failure names the list to edit. The rules and their reasons: internal-packages/observability-map/README.md. |
…nization form Co-Authored-By: Claude <noreply@anthropic.com>
2c4ee48 to
3157d9a
Compare
Requested by Chris Arderne · Slack thread
Before: If anything failed while creating an organization, the new-organization form silently reset — the name you typed disappeared, no error was shown, and the Create button became clickable again. It looked like the submit had simply not registered, so the natural next step was to retype the name and press Create again. But the organization row itself is committed early in the request, so the retry could produce a second organization.
After: The name you typed is kept, and a form-level error explains what happened and suggests checking your organization list before trying again. The failure is also logged server-side, which it wasn't before.
How: The action's catch block returned
json({ errors: { body: error.message } }), which is not a conformSubmissionResult. When that got passed touseForm({ lastResult }), conform'sreport()saw noinitialValue, reset the form, and threw the error away — hence the blank field and the missing message. The catch now returnssubmission.reply({ formErrors: [...] })wrapped in a 400, which is the shape conform expects, so the submitted value is echoed back and the error is surfaced. The page had no slot for form-level errors at all, so a<FormError id={form.errorId}>{form.errors}</FormError>was added below the fields.useActionData()is now typed asuseActionData<typeof action>()(theas anyonlastResultis gone), so a future shape mismatch here is a type error rather than a silent reset — this required dropping theActionFunctionannotation in favour ofActionFunctionArgsso the return type is inferred.✅ Checklist
Testing
pnpm run format,pnpm run lint:fixandpnpm run typecheck --filter webappwere all run locally and pass. The failure path itself was not exercised in a running dashboard — it needs an induced server error during organization creation.Changelog
The new-organization form now keeps the name you typed and shows an error when creation fails, instead of clearing itself with no explanation.
Follow-ups (not in this PR)
json({ errors: { body: ... } })is returned from 11 other route files underapps/webapp/app/routes/, and 9 of those also drive a conform form, so they carry the same latent behaviour. Left alone here to keep the diff focused on the reported path.seedDefaultBillingAlertsis awaited inline increateOrganization, holding the request open for up to 5s after the organization row is already committed. Moving it off the request path would narrow the window in which a request can fail with the organization already created.Screenshots
None — the change is a message that only appears on a server error.
💯