5.70f assumed that passing wrong-type inputs to run app would be
intercepted by @accepts(body=) and return HTTP 422 with canonical
ErrorBody details[]. This premise is wrong:
- @accepts(body=) validates the API schema (inputs must be a dict),
not the workflow-level variable types (num must be a number)
- Wrong-type workflow inputs go through the SSE execution layer,
returning an error event with status:500, not a canonical 422
- The CLI receives this via decodeStreamError, not classifyResponse,
so rawResponse is never set and error.server is never populated
The behavior tested by 5.70f (CLI rendering details[] as indented
lines) remains valid as a contract requirement but has no triggerable
E2E path on the current server. Covered by unit tests for renderHuman.
Rewrites 5 existing tests and adds 1 new test to align with the V2 ErrorBody spec
(history page: https://km.dify.langgenius.ai/wiki/spaces/Enterprise/history/490602534/):
Trigger fix (5.70d, 5.70g, 5.70h):
Before: 'run app wrong-type input' → hits SSE execution layer → HTTP 500
After: 'describe app ZERO' → hits @returns canonical 404 ErrorBody → error.server set
Result: 5.70d, 5.70g, 5.70h now pass on the current server
Trigger fix (5.70e):
Before: 'run app wrong-type input' → SSE 500, no details
After: direct fetch to GET /apps?page=not-integer → @accepts(query=) returns 422
with canonical ErrorBody and details[] (bypasses CLI client-side page validation)
Result: 5.70e now passes on the current server
Forward-looking (5.70f):
Kept 'run app wrong-type input' trigger — documents that once @accepts covers the
app run path, details lines will appear; remains red until that server change deploys
New (5.70g2):
Tests V2 spec correction: hint priority is cliHint ?? server?.hint (CLI wins).
V1 doc incorrectly said 'server wins'; V2 aligned with codebase.
Trigger: unauthenticated → 401 AuthExpired → CLI AUTH_LOGIN_HINT appears at
error.hint regardless of any server-provided hint. Passes on current server.
5.70i [P1] — /openapi/v1 unknown route 404 carries canonical ErrorBody
(code, status) and must NOT contain flask-restx route suggestions
('did you mean'); pins the ExternalApi._help_on_404 fix from
PR #37285
5.70j [P1] — device-flow token endpoint returns RFC 8628 {error: string}
on failure, not the canonical ErrorBody shape; pins the
explicit RFC 8628 exception documented in PR #37285 and
confirms zErrorBody.safeParse would fail gracefully on this
shape (serverError = undefined, generic message, no crash)
Add 5 new test cases (5.70d-h) that verify the CLI correctly forwards the
canonical ErrorBody from the server when request validation fails (422).
These tests define the E2E contract introduced by the OpenAPI ErrorBody
unification spec. They will be red until the server-side change deploys;
the spec document is at:
https://km.dify.langgenius.ai/wiki/spaces/Enterprise/pages/490602534/
5.70d [P0] — JSON envelope contains error.server with code='invalid_param',
status=422, and a non-empty message string
5.70e [P1] — error.server.details array carries field-level error entries
with the {type, loc, msg} shape from ErrorDetail
5.70f [P1] — human-readable text mode renders each details entry as
' - <loc>: <msg> (<type>)' line (no -v required)
5.70g [P1] — text mode header code is server's 'invalid_param', not CLI's
'server_4xx_other' (server code wins in renderHuman)
5.70h [P1] — JSON envelope error.code is CLI classification code
('server_4xx_other'); semantic code is in error.server.code