Skip to content

Output And Errors

Bullpen is meant to be usable by people, shell scripts, and AI agents. Use --output json when you need stable machine-readable output, support evidence, or retry decisions.

Output Modes

Most commands default to table or text output for terminal use.

bullpen portfolio balances

Use JSON for automation. This is a non-runnable sequence: run the refresh diagnostic only when refreshed auth evidence is needed.

bullpen portfolio balances --output json
bullpen polymarket wallet-audit --refresh --output json
bullpen status --output json
bullpen doctor auth --refresh --output json

Non-streaming JSON commands emit one JSON document to stdout. Streaming commands emit one JSON document per line. Commands that cannot safely mix prompts or raw interactive output with JSON reject JSON mode instead of returning partial JSON.

See the JSON Output Contract for schema-version, numeric-field, and compatibility rules.

Error JSON

When JSON mode can render an error, the CLI emits an object with stable top-level fields and optional command-specific fields.

{
  "error": "Polymarket submission returned STATE_FAILED",
  "chain": ["external submission failed after validation"],
  "hint": "Capture the trace ID and contact support before retrying.",
  "relayer_trace_id": "trace_..."
}

Consumers should accept optional fields as nullable and tolerate extra fields. Do not scrape human text when a typed field such as code, error_code, relayer_trace_id, wallet_kind, schema_version, or polymarket_status is available.

Newer error surfaces include a typed envelope in addition to legacy command-specific fields:

Field Meaning
ok false for JSON error envelopes.
code Stable dotted error family, for example auth.login_required, auth.device_login_stalled, wallet.selection_disagreement, or redeem.relayer_rejected. Prefer this field over prose or legacy error_code when it is present.
recoverability Machine-readable recovery class such as login_required, state_inspection_required, retryable_without_action, user_action_required, or support_required.
requires_login Whether login is required before retrying. Do not infer this from human text.
safe_to_retry Whether repeating the same action is safe without checking current state first.
next_command A single bullpen ... command that is safe to run next, when one exists.
support_safe_evidence Redacted support context. It may include code, legacy error_code, auth_state, operation, or bounded device-login stall counters, but never secrets.
auth_incident Auth-attempt state for device login and email verification. Inspect auth_incident.attempt_id_provenance, auth_incident.stage, auth_incident.terminal, auth_incident.safe_to_retry, auth_incident.resolution_owner, auth_incident.next_command, and auth_incident.support_code. A locally generated attempt ID is not a service correlation ID.
recovery Canonical recovery projection for Polymarket money-path failures. Prefer recovery.recovery_status or recovery.status, recovery.next_action, recovery.terminal, and recovery.safe_to_retry over scraping human text.
recovery_plan Shared account-level recovery plan from fix, recover polymarket, support, and Polymarket wallet diagnostics.
market_state Polymarket preview/rejection state such as market_resolved, orderbook_unavailable, or closed_or_resolved. When present with would_submit:false, no order was submitted.
would_submit / signature_requested / exchange_request_submitted Preview-safety fields. false means the command stopped before signing or exchange submission. Do not describe that as a CLOB rejection.
submit_requested / transaction_submitted Solana mutation fields. A post-sign provider rejection before broadcast has would_submit:true, signature_requested:true, submit_requested:true, transaction_submitted:false, and submission_state:"rejected". Do not invent rejected_pre_broadcast as a JSON enum.
signing_capability Auth diagnostic object for signing-path evidence. checked: false means this passive command did not run a signing probe; no Turnkey signing authority was confirmed or ruled out. Inspect checked, signing_capability.signing_capability, signing_capability.resolution_owner, signing_capability.next_action, and signing_capability.safe_to_retry.
delivery Support artifact delivery metadata. state: "local_file_not_uploaded" and uploaded: false mean the file is on this machine and has not been uploaded. Attach the JSON file; a local path alone does not send it to Bullpen.
originating_context Optional recent failure context for support bundles. It includes only a privacy-safe command family and typed error code from the last 24 hours, never raw arguments or error text.
privacy_contract Root disclosure metadata on shareable support or doctor JSON artifacts. It states which operational wallet/account/resource, condition, transaction, order, or trade IDs, exact balances, and local paths are included. It also states that credentials, tokens, private keys, auth headers, raw provider bodies, and raw credential error chains are excluded.

error_code remains for backward compatibility and command-specific support codes. Agents should prefer code when both fields are present.

Funds recovery JSON separates preview authorization from live retry evidence. bullpen recover funds --dry-run --output json emits dry_run: true; submit with --yes --output json emits dry_run: false.

For a dry-run preview, treat local submit as authorized only when the root status is ready, every executable leg has legs[].outcome: "supported", and every executable leg has legs[].effective_evidence.submit_authorized: true. Review legs[].source_identity, legs[].destination_identity, and legs[].route before submitting. Do not use legs[].submit.safe_to_retry as an ordinary preview submission criterion; dry-run legs have not submitted anything yet.

After a live submit, inspect legs[].submit.state, partial_execution, and legs[].submit.safe_to_retry before deciding whether another live attempt is safe. Support-required, unknown, failed, outcome-unknown, or legs[].submit.safe_to_retry: false states require checking current state before another live attempt.

Funds recovery can use selected and non-selected owned Safe, Proxy, current Deposit Wallet, deployed legacy Deposit Wallet, and locally signable owned EOA sources verified by the CLI. Self-service direct-address submit requires CLI-verified local signing authority for that exact EOA and enough native gas. Imported, external, and routing-only addresses are not local recovery sources unless the CLI verifies they are also locally signable owned EOAs. Recovery does not change the selected trading wallet; it refreshes and rechecks source identity, destination identity, and the exact transfer details at submit, then validates the full plan before the first transfer.

Recovery-oriented errors may also include support_safe_cause, retryable_without_action, recovery_action, and next_action. support_safe_cause is a string label for support routing. recovery_action names ownership of the next step. Repeat a write only when the structured output or fresh diagnostics say the current state is safe; if the same provider failure repeats, stop and send the JSON to support.

When bullpen support bundle --output json emits both next_action and support_next_action, treat next_action as the account recovery step and support_next_action as the instruction for attaching the generated support artifact. The passive JSON artifact remains local until you attach the file to a ticket. Its root privacy_contract discloses retained operational identifiers, exact balances, and local paths. It does not refresh auth, refresh wallet or balance evidence, check signing authority, or check order credit.

Wallet-routing diagnostics may include deposit_wallet_derivation: beacon_proxy, legacy_uups, or legacy_uups_fallback_rpc_unavailable. Use that field to compare diagnostics across bullpen doctor wallet, legacy bullpen polymarket wallet check, and bullpen funds diagnose-deposit. wallet-audit uses the same beacon-aware resolver internally, but does not currently emit the provenance field. Do not assume a legacy-derived address is current when the field says fallback was used because RPC was unavailable.

Balance Reconciliation

bullpen funds balances --output json may include polymarket_reconciliation when the current evidence does not support a simple single-source total. The displayed headline excludes unverified aggregate amounts and uses independently observed cash, open-position, and claimable components instead.

Use reconciliation_state and confidence before acting on the result. Treat raw_value_usd as diagnostic evidence only. Closed positions are historical and never add to the current balance. A positive claimable_redeemable_positions.value_usd is actionable only after bullpen recover redeem --dry-run --output json confirms the plan.

Auth Retry Safety

Some auth-looking errors happen after a live request has already been sent. Agents must distinguish retryable auth refresh from no-replay auth rejection.

If JSON includes requires_state_inspection: true, do not automatically retry the live command. Run the next_action diagnostics, inspect the relevant account or order state, and retry manually only when the state is known.

Redeem submissions have an additional post-submit reconciliation surface. When a live redeem emits post_submit_reconciliation, redeem_operation_id, or safe_to_retry: false, treat the original submit as non-replayable. Inspect the stored operation instead:

bullpen polymarket redeem-status <operation-id-or-tx-or-trace> --output json

The JSON status includes transaction_state, value_state, resolution_owner, next_action, safe_to_retry, and the stored record. safe_to_retry is always false for redeem status results. Pending indexing, missing evidence, reverted receipts, wrong-wallet settlement, and contradictory evidence are support or wait-and-recheck states, not automatic retry states.

No-replay auth classes include account-mutation, Pear mutation, and redeem mutation auth rejections.

The account-mutation no-replay class covers writes such as email OTP send, wallet private-key import, deposit-wallet deploy/reregister, wallet selection/nickname/visibility, notification mark/preference, portfolio or PnL refresh with refresh=true, pre-swap transfer submit, Solana transaction submit/record flows, Polymarket contract-wallet selection, wallet-tracker add/remove, Turnkey API-key revoke, and copy-trading mutations. It means Bullpen sent the write once and did not refresh/replay after auth rejection.

Email verification may instead report auth_incident.stage: "email_otp_request" with safe_to_retry: false. This means the service-call outcome was not confirmed and the CLI did not replay the request. Follow next_command; when support is required, run bullpen support bundle --output json and attach the generated local support artifact rather than requesting another code or repeating login.

HYPERLIQUID_COPY_RAW_TOKEN_AUTH_REJECTED means the caller used a raw-token Hyperliquid copy context. Raw-token contexts cannot refresh Bullpen auth in place, so the error is not retryable with the same token. Route through normal CLI auth or inspect bullpen status --output json plus bullpen doctor auth --refresh --output json before deciding whether human login is required.

For these errors, retryable and retryable_without_action are false. This is different from safe read retries or the narrow Polymarket CLOB auth refresh path that reuses the same order body and idempotency key once.

Hyperliquid copy-trading errors may use HYPERLIQUID_COPY_SERVICE_REJECTED or HYPERLIQUID_COPY_SERVICE_UNAVAILABLE when the CLI can identify the copy context. Before escalating, run bullpen hl copy list --include-stopped --output json, verify whether the failed command expects a subscription id or leader address, and capture the failed command again with --output json.

HYPERLIQUID_MARGIN_INSUFFICIENT means Hyperliquid accepted the selected market route but rejected the order because the account did not have enough usable margin for that market context. This can happen on HIP-3 DEXes even when price reads and previews work. Run bullpen hl balances --output json and bullpen hl status --all-dexes --output json, reduce size, or add usable margin before retrying.

An uncertain live Hyperliquid /exchange write is not the same as preview or pre-submit validation. All uncertain /exchange reports share request_attempted:true, submission_state:"outcome_unknown", requires_state_inspection:true, safe_to_retry:false, retryable:false, retryable_without_action:false, and auto_retried:false.

The transport-stage fields identify how far the client can prove the request went:

Uncertainty stage Transport fields Meaning
Send uncertainty exchange_request_submitted:null, submitted:null The client cannot prove whether Hyperliquid received the request.
Response body read uncertainty exchange_request_submitted:true, submitted:true Hyperliquid returned an HTTP response, but the client could not read the response body enough to interpret the outcome.
Successful response parse uncertainty exchange_request_submitted:true, submitted:true Hyperliquid returned an HTTP response, but the client could not parse the response into a known outcome.

Inspect account state and open orders before any manual retry.

SOLANA_MARKET_DATA_UNAVAILABLE means a Solana market-data endpoint such as token whales reached Bullpen APIs but the upstream read failed. Treat it as a read-side provider issue. It is not a Polymarket routing failure and does not require wallet repair or re-login unless diagnostics separately say auth is invalid.

TURNKEY_POLICY_DENIAL means Turnkey rejected the requested activity by account policy, for example ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2. This is a server-side account repair. Do not loop on bullpen login, CLOB API-key reset, or CLI upgrades. Capture bullpen status --output json and the refreshed auth diagnostic (bullpen doctor auth --refresh --output json), then open or continue a Bullpen support ticket so support can grant the missing Turnkey activity permission.

Plain doctor auth --output json and support bundle --output json are passive capture commands. They include signing_capability separately from token validity and credential decryptability. When signing_capability.checked is false, the CLI did not build a signer, call Turnkey signing, or diagnose Turnkey resource availability through a signing request. Treat signing_capability.signing_capability: "unknown" with resolution_owner: "not_checked" as "not checked", not as ready and not as a confirmed Turnkey failure.

bullpen doctor auth --refresh --output json explicitly refreshes auth before diagnostics, but refresh evidence is still not signing evidence unless the output says signing_capability.checked: true and the source command actually performed a signing probe. A money-command error such as turnkey_resource_missing or a Turnkey provider failure is live-path evidence from that command, not something passive diagnostics confirmed in advance. Capture the failing command's JSON and a support bundle, then follow the typed next_action; do not repeatedly re-login unless diagnostics report login is required.

doctor auth reports local credential-store failures as sanitized credentials_error text plus nullable credential_error_class. Non-null class values are missing, decrypt_failed, decode_failed, permission_denied, store_locked, or unknown. Use the class for routing; do not ask users to attach raw credential-store errors.

Resolved or closed Polymarket previews may return market_state with would_submit:false, signature_requested:false, and exchange_request_submitted:false. For market_resolved, use bullpen recover redeem --dry-run --output json if you hold outcome tokens. For orderbook_unavailable, search/discover an active market or wait for a live orderbook instead of retrying the same preview as if an order failed.

Exit Codes

Scripts and agents should check the process exit code before deciding whether to retry.

Exit code Meaning Typical response
0 Success Continue.
1 General or unknown error Read the JSON/prose error and avoid blind retry loops.
2 Authentication failure Run bullpen status --output json and bullpen doctor auth --refresh --output json, then inspect typed code, requires_login, safe_to_retry, and next_command. Log in only for auth.login_required, auth.refresh_rejected, or login-required diagnostics. Fix writable storage for AUTH_REFRESH_PERSISTENCE_FAILED. Retry writes only when structured fields or fresh diagnostics verify the current state is safe; raw-token, no-replay, requires_state_inspection=true, and non-idempotent mutation paths require inspection or re-auth first.
3 Usage, validation, or confirmation failed before execution Fix the command, flags, amount, prompt behavior, or input data.
4 Execution failed after validation Inspect the typed error; support may be needed for upstream/account-state failures.
5 Network, timeout, or connection failure Retry only when idempotent or after checking service health.
6 Polymarket submission service degraded Capture trace IDs and support output; do not repeat live submits indefinitely.
7 CLI version below supported minimum Run bullpen upgrade.
13 Polymarket wallet selection disagrees with on-chain evidence Run bullpen polymarket wallet-audit --refresh --output json and contact support.
14 Turnkey wallet resource is missing Run bullpen status --output json and bullpen doctor auth --refresh --output json, then contact support if it persists.

Support-Grade Capture

When reporting a CLI issue, capture the smallest set of JSON outputs that shows the failure class:

bullpen --version
bullpen status --output json
bullpen doctor auth --output json
bullpen doctor wallet --output json

This is passive capture. When you need to decide whether login, refresh, or a retry is safe, use bullpen status --output json plus the refreshed auth diagnostic (bullpen doctor auth --refresh --output json) instead of relying on plain doctor auth.

For Polymarket wallet, trade, redeem, or withdraw failures, add:

bullpen polymarket wallet-audit --refresh --output json

For redeem failures, first include the dry-run output:

bullpen polymarket redeem --dry-run --output json

Live: include live-submit output only after the dry-run confirms the redeemable plan and you intentionally submit it.

bullpen polymarket redeem --yes --output json

Do not share private keys, seed phrases, JWTs, API tokens, full config files, or unredacted logs. Raw logs are exceptional support evidence; attach them only when support asks after JSON artifacts are insufficient, and manually scrub credentials, tokens, private keys, auth headers, raw provider bodies, raw credential error chains, and unrelated local paths first.

Agent Guidance

Agents should prefer this sequence:

  1. Run a read-only command with --output json.
  2. Check exit code and typed error fields.
  3. For money-moving commands, run --preview or --dry-run first when the command supports it.
  4. Use --yes only when the user explicitly asked for the live action and the preview/dry-run is acceptable.
  5. Stop and ask for human review on wallet-routing disagreement, Polymarket submission STATE_FAILED, unsupported withdraw, unknown error, or repeated network failure.

See also: