Skip to content

fix(settings): surface API error envelopes in the storage tab instead of crashing (#14846) - #14951

Merged
diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.51from
shipsfromrio:fix/settings-backup-error-message
Sep 28, 2026
Merged

diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.51from
shipsfromrio:fix/settings-backup-error-message

Conversation

@shipsfromrio

Copy link
Copy Markdown
Contributor

Summary

In Settings > Storage, "Backup now" and "Import Database" crash the whole settings page into its error boundary ("Failed to load settings"). "Export Database" shows Export failed: [object Object].

SystemStorageTab used data.error || t(...) as the status message. When the API answers with the structured envelope { error: { code, message, correlation_id } }, that object is rendered as a React child ("Objects are not valid as a React child"), which triggers settings/error.tsx. The download helper did new Error(data.error || fallback), which turns the object into [object Object].

/api/db-backups* has been in ALWAYS_PROTECTED_API_PATHS since before v3.8.50 (the reporter's version). A dashboard session without auth therefore gets exactly this envelope from the authz pipeline (rejectionResponse in src/server/authz/pipeline.ts). The route handlers also return object-shaped error values for validation failures (restore, retention, cleanup).

Every error-status message in the tab, and fetchAndDownload, now goes through the existing extractApiErrorMessage() (src/shared/http/apiErrorMessage.ts), the helper already used for #5340 and #5991. Plain string errors from the route handlers are shown as before.

Related Issues

Closes #14846

Validation

  • npx vitest run tests/unit/ui/system-storage-backup-auth-envelope-14846.test.tsx: 2/2 pass. With only the component reverted to the base version, both fail with Objects are not valid as a React child (found: object with keys {code, message, correlation_id}) and exportFailedWithError: [object Object].
  • node --import tsx/esm --test tests/unit/ui/system-storage-error-envelope-14846.test.ts: 5/5 pass, 3 fail on the base version.
  • Existing tests still pass: npx vitest run tests/unit/ui/system-storage-manual-vacuum.test.tsx tests/unit/ui/system-storage-tab-guest-401-12709.test.tsx, and node --import tsx/esm --test tests/unit/dashboard-localization-contract.test.ts tests/unit/quota-card-grid-mobile-7072.test.ts tests/unit/settings-ui-layout-static.test.ts tests/unit/api-error-message-5340.test.ts (27/27).
  • npx eslint and npx prettier --check are clean on the touched files.

Tests Added

  • tests/unit/ui/system-storage-backup-auth-envelope-14846.test.tsx: renders the tab with a 401 AUTH_001 envelope from /api/db-backups and clicks "Backup now" and "Export Database". It checks that the tab stays mounted, that the envelope message is shown, and that [object Object] never appears.
  • tests/unit/ui/system-storage-error-envelope-14846.test.ts: a source guard against message: data.error || and new Error(data.error) in the tab, plus extractor checks on the pipeline envelope, string errors and empty bodies.

Coverage Notes

The .sqlite import confirm flow (file input plus modal) is covered by the source guard, not by a render test. It uses the same code path as "Backup now".

Reviewer Notes

… of crashing

/api/db-backups* are always protected, so an unauthenticated dashboard
session receives the authz pipeline envelope
{ error: { code, message, correlation_id } }. SystemStorageTab used
`data.error || t(...)` as the status message, rendering that object as a
React child (settings error boundary: "Failed to load settings"), and
wrapped it in `new Error(...)` in the download helper, which produced
"Export failed: [object Object]".

Route every error-status message and the download helper through the
existing extractApiErrorMessage() helper.

Closes diegosouzapw#14846
@diegosouzapw
diegosouzapw merged commit 7a326b2 into diegosouzapw:release/v3.8.51 Sep 28, 2026
3 checks passed
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.

fix: Failed to load settings

2 participants