Repository navigation
Commit aad5ee0
fix(app-shell): a route whose object read the server answered shows the server reason, not "check your connection" (#29883)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} -->
_Requested by **Steedos** · [project
thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9Ubb1XxsxCUUTENZK7nrfYe3Zo)_
Fixes #29728
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么**:应用路由读取对象定义失败时,如果服务器其实已经回答了(5xx,或带有本版本不认识的错误码的
404),页面现在显示服务器给出的原因和错误码,而不再让人「检查网络连接」。
-
**为什么改**:服务器明明说了原因,界面却让用户去排查网络,误导用户也误导排障;列表页、记录页、应用页早已按同一规则显示服务器原因,路由级这一处是最后一个。
- **风险与回滚**:风险低。适配器只是在抛出的包装错误上多带一个
`details.originalError`,类、code、statusCode、message 都不变;网络中断和 403
仍显示原来的文案,重试行为不变。回滚即还原本 PR。
- **先看**:`ui/packages/data-objectstack/src/index.ts`(getObjectSchema 的非
404
分支)、`ui/packages/app-shell/src/providers/MetadataProvider.tsx`(失败读取保存服务器回答)、`ui/packages/app-shell/src/console/AppContent.tsx`(RouteObjectReadFailed)。
- **两分钟验证**:在 `ui/` 下运行 `pnpm exec vitest run
packages/app-shell/src/console/__tests__/AppContent.disabledPackageDeepLink-13052.test.tsx`,预期
18 个用例全部通过,其中 503 用例显示 SERVICE_UNAVAILABLE 和服务器原文。
- **需要你做的**:无,席位落地。
## What changes
On main, an app route whose by-name object read failed drew "Check your
connection and try again" whatever happened: an answered 503, an
answered 500, a 404 with a code this build does not know, a network drop
and a 403 all drew the same sentence. Measured on `99c06965` through the
real `ObjectStackAdapter` under the real `MetadataProvider` and
`AppContent`.
The provider never saw the server's answer. `requestObjectSchema` throws
`Error{status, code, message}` with the server's own code and sentence,
but `getObjectSchema`'s non-404 catch rewrapped it with
`createErrorFromResponse` and kept no reference to it. A 503 became
`ConnectionError` `CONNECTION_ERROR` "Connection error: ...", a 500
became `UNKNOWN_ERROR`, and a network drop got an invented status 500.
- **`@object-ui/data-objectstack`**: `getObjectSchema`'s non-404 rewrap
now carries the transport error as `details.originalError`, as its 404
arm (`MetadataNotFoundError`) and three other wrap sites in the package
already do. The wrapper's class, `code`, `statusCode` and `message` are
unchanged, and `createErrorFromResponse` keeps its signature.
- **`MetadataProvider`**: `readObjectThroughAdapter` unwraps
`details.originalError` for any `ObjectStackError` (before, only
`MetadataNotFoundError`). A failed by-name read stores
`answeredLoadFailure(err)` beside the failed name, in a new `answers`
record on the scope entry. Nothing is stored for a refused read
(`forbidden` / `unauthorized`), which keeps its state as `PageView`
does. The record is dropped when the name is answered or invalidated,
and returned beside `failed` / `refused`.
- **`appObjectScope`**: `failedAnswer` is the answer of the first failed
name that has one. It is carried on the object, page and dashboard route
paths.
- **`AppContent`**: `RouteObjectReadFailed` draws `answer.message` in
place of the network sentence, plus a code chip
(`route-object-read-failed-code`) in `PageView`'s shape. No i18n rows
were added, and Retry is unchanged.
## Tests
- `AppContent.disabledPackageDeepLink-13052.test.tsx`: a new top-level
describe over the REAL adapter driven by a fake `fetch`. It pins:
- an answered 503 (wrapped envelope), a 500 (flat envelope) and an
unknown-code 404 each show the server code and sentence, and not the
network sentence;
- a page route that binds the object shows the 503 answer too;
- CONTROLs: a network drop keeps the network sentence with no chip; a
403 keeps today's state; `RESOURCE_NOT_FOUND` and
`OBJECT_PACKAGE_DISABLED` keep theirs;
- Retry still asks once more and clears the answer, and a retry that
gets no answer draws the network sentence again.
- `getObjectSchema.test.ts`: a new describe pins the wrapper's class,
code, statusCode and message, plus `details.originalError`, for a 503, a
500 and a network drop, and a 404 CONTROL.
<details><summary>Ablations (committed head, ablation-replace.mjs,
restored blob == HEAD)</summary>
- Drop the provider unwrap (back to `MetadataNotFoundError` only): 5 of
9 new route pins went red (503, 500, page 503, network CONTROL,
retry-to-network). The unknown-404 pin stayed green, because a 404 is
still unwrapped.
- Drop the `answers` record (`if (answer && false)`): 6 of 9 went red
(503, 500, unknown-404, page 503, both Retry pins).
</details>
<details><summary>Verification</summary>
- Related sweep: 301 app-shell test files naming `appObjectScope` /
`AppContent` / `MetadataProvider` / `route-object-read-failed` (6
batches, all green), plus the whole data-objectstack suite (114 files,
green).
- `turbo run type-check --filter=@object-ui/app-shell
--filter=@object-ui/data-objectstack`: 66/66 tasks.
- eslint on the six touched files: 0 errors.
- Derived gates (`dispatch-gates --commands`): 36 derived, 36 run, all
exit 0, reconciled with `--ran` (0 NOT-MEASURED), at `ff352f41`. The
head `effe42c8` adds only a merge of one unrelated main commit
(cloud-connection).
- Sweep, type-check and ablations ran at `2a886b17` / `ff352f41`; the
touched files are unchanged since.
</details>
## Acceptance notes
- **Verdict edge:** with the unwrap, a non-404 status that carries
`RESOURCE_NOT_FOUND` or `OBJECT_PACKAGE_DISABLED` is now read by its
code: an absence or a refusal, not a failure. No server path is known to
answer that way.
- **Finding, filed by the seat:** `createErrorFromResponse` stamps `500`
on any error with no status. As a result, every `getObjectSchema` caller
that reads the wrapper takes a network drop for an answered 500 (43
source files, 58 call sites under `ui/`). This PR reads the cause
instead and leaves the wrapper as it is.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QsR2jTGjiGTnPZnatdavVb)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 00f72f9 commit aad5ee0
7 files changed
Lines changed: 391 additions & 26 deletions
File tree
- .changeset
- ui/packages
- app-shell/src
- console
- __tests__
- providers
- data-objectstack/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
| 17 | + | |
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| |||
475 | 475 | | |
476 | 476 | | |
477 | 477 | | |
| 478 | + | |
478 | 479 | | |
479 | 480 | | |
480 | 481 | | |
| |||
1553 | 1554 | | |
1554 | 1555 | | |
1555 | 1556 | | |
| 1557 | + | |
1556 | 1558 | | |
| 1559 | + | |
1557 | 1560 | | |
1558 | 1561 | | |
1559 | 1562 | | |
| |||
2137 | 2140 | | |
2138 | 2141 | | |
2139 | 2142 | | |
| 2143 | + | |
| 2144 | + | |
| 2145 | + | |
| 2146 | + | |
| 2147 | + | |
| 2148 | + | |
| 2149 | + | |
2140 | 2150 | | |
2141 | | - | |
| 2151 | + | |
2142 | 2152 | | |
2143 | 2153 | | |
2144 | 2154 | | |
| |||
2148 | 2158 | | |
2149 | 2159 | | |
2150 | 2160 | | |
2151 | | - | |
| 2161 | + | |
2152 | 2162 | | |
2153 | 2163 | | |
2154 | 2164 | | |
| 2165 | + | |
| 2166 | + | |
| 2167 | + | |
| 2168 | + | |
| 2169 | + | |
| 2170 | + | |
| 2171 | + | |
| 2172 | + | |
2155 | 2173 | | |
2156 | 2174 | | |
2157 | 2175 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
21 | 27 | | |
22 | 28 | | |
23 | 29 | | |
| |||
35 | 41 | | |
36 | 42 | | |
37 | 43 | | |
38 | | - | |
| 44 | + | |
39 | 45 | | |
40 | 46 | | |
41 | 47 | | |
| |||
307 | 313 | | |
308 | 314 | | |
309 | 315 | | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
0 commit comments