Skip to content

CLI hides the API's reason for an error #650

Open

Description

@kvz

Why

The API explains what is wrong in reason, but the CLI only prints message, so people see a generic error and cannot fix their command.

Found while dogfooding builtin/extract-text for the documents blog post:

$ npx -y @transloadit/node assemblies create --template builtin/extract-text \
    --field text_format=md --field text_granularity=page -i report.pdf -o out/
err     API error (HTTP 400) INVALID_FORM_DATA: The form contained bad data, which cannot be parsed. https://api2-….transloadit.com/assemblies/<assembly-id>

The Assembly Status for that same request carries the actual cause:

{
  "error": "INVALID_FORM_DATA",
  "message": "The form contained bad data, which cannot be parsed.",
  "reason": "Invalid Builtin Template field “fields.text_granularity”: The page text_granularity is only supported for native text extraction."
}

With the reason on screen the fix is obvious (add --field text_method=native). Without it, "The form contained bad data" points at the upload, not at a field.

What

  • ApiError builds its message from error, message and assembly_ssl_url only (packages/node/src/ApiError.ts). reason is stored on the error but never shown.
  • formatAPIError in packages/node/src/cli/helpers.ts prints err.message, so every CLI command drops the reason.

Suggested: have the CLI's formatAPIError append a string reason when the API sent one (and keep structured rawReason out of the one-line output). Whether ApiError.message itself should also include it is a separate call, since SDK users may match on the message.

Done when

The command above prints the reason, and a test covers an API error with and without a reason.

Activity

  1. self-assigned this
    on Nov 11, 2026
  2. kvz commented on Nov 11, 2026

    @kvz
    MemberAuthor

    A second case of the same problem, found on 2026-11-11 while storing blog figures.

    $ npx -y @transloadit/node storage store press-kit-page.jpg blog/2026-11-llm-ready-markdown/ --workspace my-app --public --json
    Workspace verification failed (HTTP 400). Check the Storage API … dam:read or dam:write scope.

    The Auth Key had the right scopes. Calling the API directly showed the real reason:

    INVALID_SIGNATURE: Sign DAM requests for their method and path, in auth.method and auth.path.
    

    So the CLI replaced a precise, actionable API message with a guess about scopes that sent me in the wrong direction. Showing the API's error and message next to (or instead of) the hint would have made this a one-minute diagnosis.

    Separate from the reporting problem: the cause here is that production now requires method/path-bound signatures on /dam/* (api2#11023, merged 2026-11-09), while the SDK change that sends them (#648) is not merged or released yet. Until it is, Storage commands in @transloadit/node 6.7.0 and older fail this way in production.

  3. kvz commented on Nov 12, 2026

    @kvz
    MemberAuthor

    The cause of this second case is fixed in @transloadit/node@6.8.0 (#648): Storage requests now sign their method and path. Checked against production on 2026-11-12: storage ls fails with 6.7.0 and works with 6.8.0. The subject of this issue is unchanged: with 6.7.0 the CLI still printed only “Storage listing failed (HTTP 400)” and not the reason the API gave.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions