Skip to content

fix(init): show why initialization failed instead of a bare 500 - #674

Merged
PIKACHUIM merged 7 commits into
mainfrom
fix/init-error-visibility
Sep 18, 2026
Merged

PIKACHUIM merged 7 commits into
mainfrom
fix/init-error-visibility

Conversation

@PIKACHUIM

Copy link
Copy Markdown
Member

fix(init): show why initialization failed instead of a bare 500

Base: mainCompare: fix/init-error-visibility
Commit: c5f6671 · Files changed: 4 (+126 / −3)
Open PR: https://github.com/OpenListTeam/OpenList-Frontend/pull/new/fix/init-error-visibility
配套后端 PR: fix/init-setup-empty-storeOpenList-Worker8daf341 + 1dba9ad
https://github.com/OpenListTeam/OpenList-Worker/pull/new/fix/init-setup-empty-store

Summary / 摘要

初始化失败时,安装向导只弹一条 toast,用户拿不到任何可操作信息:后端返回的
message 被通用文案覆盖,结构化原因(data.code / data.reason)在请求层就被
丢弃,页面也没有持久展示位。用户看到的就是「点了初始化 → 失败 → 不知道为什么」。

本 PR 让向导把原因说清楚:失败原因与错误码内联展示在「管理员账号」步骤;后端自报
的存储问题(init_status.storage_error / db_load_error)在任何步骤都可见;HTTP
错误不再丢掉响应体与服务端文案。

When initialization fails the wizard only showed a transient toast: the server's
structured reason (data.code / data.reason) was dropped by the request layer
and the page had nowhere to display it. This PR surfaces the reason inline, keeps
the backend-reported storage problem visible on every step, and stops discarding
the response body on HTTP errors.

Behavior Changes / 行为变化

User-visible behavior changes / 用户可感知的行为变化:

  • 初始化失败后回到「管理员账号」步骤时,会持续展示具体原因与错误码:

    初始化失败
    Unsupported storage combination: DB_FORMAT="sql" cannot be used with
    DB_DRIVER="kv". Driver "kv" supports: map | key. The "sql" format needs a
    relational driver (SQL query support): d1 | do | mysql.
    错误码                                          INVALID_COMBINATION
    
  • 后端自报的存储问题在所有步骤都可见(含修复提示),不再出现「未初始化 + 无原因」:

    检测到存储问题
    DB_DRIVER is set to "d1", but that driver is not available in this runtime.
    The "d1" driver requires a Cloudflare D1 binding named "DB" (wrangler.jsonc:
    "d1_databases": [{ "binding": "DB", ... }]).
    请先修复存储配置,重新执行环境自检后再试。
    
  • 环境自检面板(EnvCheck.tsx)无需改动即受益:issue 的 message 现在包含后端
    给出的具体原因,并新增 STORAGE_INVALID_COMBINATION 这条(含文档链接)。
    非法组合不再是「自检全绿 → 提交 → 500」。

  • HTTP 错误的提示文案改为服务端文案(例如「database is not readable…」),
    而不是 axios 的 Request failed with status code 500

Important implementation changes / 重要实现变化:

  • src/utils/request.ts:错误拦截器保留响应体并优先使用服务端 message
    { code, message, data }),网络错误/超时仍回退 axios 的 message。
    这是本 PR 能让上层拿到 data.reason 的前提。

  • src/pages/init/index.tsx

    • 新增 failure():失败时记录 data.code / data.reasonreason 缺失时回退
      服务端 message),成功提交时清空;
    • 新增 storageIssue()onMount 读取 /public/init_status
      storage_error / db_load_error,在步骤指示器下方常驻展示;
    • 失败原因块只在「管理员账号」步骤渲染(失败时用户会被带回该步骤)。
  • src/types/init.ts:新增 InitSetupErrorInitStatus 增加
    storage_error / db_load_error / db_trustedEnvCheck.storage 增加
    error_code / error_message

  • src/lang/en/init.json:新增 4 个键(error_title / error_code /
    storage_issue_title / storage_issue_hint)。

  • This PR has breaking changes.
    / 此 PR 包含破坏性变更。

  • This PR changes public API, config, storage format, or migration behavior.
    / 此 PR 修改了公开 API、配置、存储格式或迁移行为。

  • This PR requires corresponding changes in related repositories.
    / 此 PR 需要关联仓库同步修改。(后端 OpenList-Worker

Related repository PRs / 关联仓库 PR:

Related Issues / 关联 Issue

Relates to OpenListTeam/OpenList-Worker#62 —— 该 issue 的三条现象中,「全新空存储
向导 500」「配置 ADMIN_PASS 仍跳 /@init」由配套后端 PR 修复;本 PR 负责让用户在
页面上看见失败原因(issue 正文里「期望:应能通过向导完成首次初始化 / 至少给出
可操作提示」的前端部分)。

Root Cause / 根因分析

POST /public/init/setup → 500 { message, data: { code, reason } }
        │
        ├─ 旧:axios 拦截器  ──► { code: 500, message: "Request failed with status code 500" }
        │                        (响应体被丢弃 → data.reason 永远拿不到)
        │      └─ 向导:handleRespWithoutAuthAndNotify → notify.error(msg) → 一条 toast,一闪而过
        │
        └─ 新:拦截器保留响应体 + 服务端 message
               └─ 向导:failure() 常驻展示 code/reason;storageIssue() 展示后端自报问题
  1. 响应体被丢弃src/utils/request.ts 的错误分支只返回
    { code: error.response?.status, message: error.message },服务端的
    messagedata 全部丢失,前端无论怎么改都拿不到原因。
  2. 没有展示位:向导失败时只调用 notify.error(...) 弹 toast,随后回到第 2 步,
    页面没有任何地方保留失败信息;用户重试时只能靠猜。
  3. 后端字段未被消费:后端已在 /public/init_status 返回
    storage_error / db_load_error(见配套 PR),但前端从未读取,导致
    「存储不可用」只能表现为「未初始化」加一个 500。

Testing / 测试

  • npx tsc --noEmit -p tsconfig.json:改动文件(utils/request.ts
    types/init.tspages/init/index.tsx无错误(仓库在 main 上本来就有
    若干与本次无关的既有类型错误,例如 Monaco / archive 预览相关)
  • npx prettier --check(改动文件):通过
  • pnpm build需要本地执行。本机沙箱对批量删除有保护,
    vite-plugin-static-copy 覆盖既有 dist/(500+ 文件)时被拦截
    SAFE_DELETE_BULK_CONFIRM_REQUIRED),与本次改动无关
  • Manual test / 手动验证(建议场景,需配合后端配套 PR):
    1. DB_DRIVER=kv + DB_FORMAT=sql(无效组合)→ 第 1 步红框列出非法组合 +
      STORAGE_INVALID_COMBINATION 文档链接;若强行提交,第 2 步显示同名原因与错误码;
    2. DB_DRIVER=d1 但未绑定 D1 → 第 1 步提示需要 d1_databasesinit_status
      storage_error 常驻显示;
    3. 后端读取失败(如绑定临时失效)→ 第 2 步显示 STORAGE_READ_FAILED 原因;
    4. Go 后端(无 env_check / 无 storage_error)→ 步骤仍为两步,界面不出现空白的
      红框,行为与改动前一致。

Reviewer Notes / 审阅提示

  • request.ts 的影响面是全局的:所有失败请求的提示文案都会从 axios 文案改为
    服务端文案,并多出一个 data 字段(仅在错误路径)。这是有意为之(服务端文案更
    有用),但请确认可接受。
  • 类型收窄Resp<T>.data 的类型仍是 T;错误路径下实际是
    InitSetupError,页面里用 (resp as any)?.data as InitSetupError | null 取用,
    避免动 Resp 的通用类型(那会波及全部调用方)。
  • 与后端的上线顺序:后端先合入效果最好;即使后端未更新,前端也只是
    reason 回退为服务端 message(或原有 toast),不会出现空框或报错
  • i18nsrc/lang/en/ 是唯一被 git 跟踪的语言目录,其余语言由 Crowdin 生成
    .gitignore 忽略)。本 PR 只加英文键,其它语言按既有机制回退英文;中文翻译需在
    Crowdin 侧同步。
  • 未改动 EnvCheck.tsx:它已经按 issues[] 渲染「消息 + 文档链接」,后端把原因写进
    message 后面板自动受益,无需重复实现。

The setup wizard only surfaced the backend's generic message, so a storage misconfiguration (invalid DB_DRIVER x DB_FORMAT pair, missing binding, read failure) ended as an unexplained failure toast with no way forward.

- request: keep the response body on HTTP errors and prefer the server's message, so callers can read structured reasons (data.code / data.reason) instead of 'Request failed with status code 500'.
- init page: remember and display the failure reason + error code inline on the admin-account step (the step users are returned to), and show the backend-reported storage problem (/public/init_status storage_error, db_load_error) on every step.
- types: add InitSetupError, InitStatus.storage_error/db_load_error/db_trusted and EnvCheck.storage.error_code/error_message.
- i18n: add the new labels to the English source dictionary (other locales fall back to English).

Pairs with the backend change that reports STORAGE_INVALID_COMBINATION and per-driver 'what is required' hints; without it the wizard could not distinguish 'combination is wrong' from 'binding is missing'. Verified with tsc (no errors in the touched files) and prettier. A full vite build cannot run in this sandbox (vite-plugin-static-copy triggers the environment's bulk-delete guard on the existing dist/), so please run pnpm build locally.
The previous commit attached data to every error response. An invariant documented in multipart.ts relies on a transport-level failure resolving to a bare {code, message} WITHOUT a data key (a real server envelope always carries one) to tell retryable transport failures from server verdicts, including flow control (429/409). Adding data: null for CDN/gateway errors (HTML body) would have made those look like envelopes and changed the upload retry / flow-control branches.

Only attach data when the server actually sent a non-null one: the mpRequest probe stays intact while the init wizard still gets the structured reason (data.code / data.reason) it needs. multipart.ts:59 is the only place in the codebase using the data in resp probe.

Verified: prettier clean, tsc reports no errors in the touched files.
…river

The backend now degrades to the auto-detected backend when the configured
driver is unavailable (instead of 503-ing every request) and reports that
as a warning, together with a one-line suggestion for both failures and
fallbacks. Surface both in the setup wizard.

- types: EnvCheckIssue.suggestion, EnvCheck.storage.suggestion,
  InitStatus.storage_warning / storage_suggestion, InitSetupError.suggestion.
- env check panel: render "How to fix" above the docs link, so the action
  cannot be lost inside a long multi-line reason.
- wizard: warning banner for a fallback (site usable, but data lands on a
  different backend than configured) and the suggestion inside the
  setup-failure box.
- i18n: env_fix_title / storage_warning_title (English source, other
  locales fall back to English).
The backend no longer switches to another backend when the configured driver
is unavailable, so there is nothing to warn about: a misconfigured driver is
reported as an error, including the driver auto-detection would have picked
and a one-line suggestion. The existing problem banner and the env-check
panel already render that.

- types: drop InitStatus.storage_warning
- init page: drop the warning signal/banner; keep the suggestion line (and
  EnvCheckIssue.suggestion) for real configuration errors
- i18n: drop storage_warning_title
…rose

The backend now exposes `summary` (a complete one-line sentence) next to the
full diagnostic text, and reports a single issue per problem. Render that:

- env check panel: show issue.summary (fall back to message for older
  backends) so a box no longer reads like "Storage driver is not configured
  correctly: DB_DRIVER is set to "do", but that driver is not availa…"
- setup failure box: prefer failure.summary over the truncated reason
- types: EnvCheckIssue.summary, EnvCheck.storage.summary,
  InitSetupError.summary
Step 1 rendered the problem twice: the banner (from /public/init_status) and
the environment panel (from /public/env_check) both showed the same reason and
the same "How to fix", which reads like two separate problems.

- the banner now renders only on the steps where the panel is not visible
  (2/3); when the backend has no self-check at all it still shows on step 1
- the "once the environment is ready, continue..." line is hidden while the
  environment is blocked, since the panel already says "Resolve the issues
  above to continue"
@starssr

starssr commented Sep 18, 2026

Copy link
Copy Markdown

大佬 我怎么用你这个修复好的

@PIKACHUIM
PIKACHUIM requested review from jyxjjj and xrgzs September 18, 2026 08:22
@PIKACHUIM
PIKACHUIM merged commit d35638d into main Sep 18, 2026
1 check passed
@PIKACHUIM
PIKACHUIM deleted the fix/init-error-visibility branch September 18, 2026 10:07
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.

3 participants