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.
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:
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:
For redeem failures, first include the dry-run output:
Live: include live-submit output only after the dry-run confirms the redeemable plan and you intentionally submit it.
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:
- Run a read-only command with
--output json. - Check exit code and typed error fields.
- For money-moving commands, run
--previewor--dry-runfirst when the command supports it. - Use
--yesonly when the user explicitly asked for the live action and the preview/dry-run is acceptable. - Stop and ask for human review on wallet-routing disagreement, Polymarket submission
STATE_FAILED, unsupported withdraw, unknown error, or repeated network failure.
See also: