Skip to content

Auth And Config Recovery

Purpose

Use this guide when login works on one machine but not another, a support run uses the wrong Bullpen profile, copied credentials fail to decrypt, or auth diagnostics mention missing local credential files. Start with read-only diagnostics and generated command references before removing local state.

This guide covers local auth and profile recovery only. It does not repair server-side account, KYC, wallet-routing, or funds state.

Before You Start

  • Run every command from the same shell, machine, and Bullpen account that saw the failure.
  • Do not delete ~/.bullpen as the first recovery step. It can remove config, logs, local keys, and wallet-routing evidence.
  • Do not copy or paste private keys, seed phrases, JWTs, API tokens, credentials.json.enc, or full config files into support tickets.
  • Set both BULLPEN_HOME and BULLPEN_CONFIG when isolating a support or CI profile. Setting only one can mix credentials from one profile with config from another.
  • Keep local/dev binaries on a separate BULLPEN_HOME from the official release profile. Do not let a local or development binary write the default ~/.bullpen credential home unless you intentionally opt in to testing that profile.

Safe First Command

Run status, auth, and config diagnostics before reauthentication or local reset. status, doctor auth, and config show are read-only. Use doctor auth --refresh --output json only when stale or expired session evidence is needed, support asks for it, or diagnostics explicitly request refreshed evidence before login or reset.

bullpen status --output json
bullpen doctor auth --output json
bullpen config show --output json

status reports local login and environment state. doctor auth reports token health, onboarding state, wallet readiness, local credential-file health, and a credential_storage object without refreshing credentials. The storage object is non-mutating and helps support distinguish encrypted credentials, legacy plaintext credentials, both files, no local credentials, and ephemeral test stores without decrypting or rewriting local auth files. config show reports effective config without printing secrets. See the generated doctor auth and config show references for exact flags.

A logged-in session is three credentials with different lifetimes: the JWT access token (~15 minutes, auto-refreshed), the refresh token (~30 days), and the signing session (~7 days). A normal access-token expiry should refresh automatically. Run bullpen login only when diagnostics report that the refresh token was rejected or the signing session must be renewed. Do not delete local state unless the CLI explicitly identifies unrecoverable credential storage. If a command fails during a transient refresh, run bullpen doctor auth --refresh --output json once and follow its structured next action.

Refresh responses must contain a non-empty access_token and a non-empty refresh_token. Missing or empty token fields are not treated as a partial success: a missing or empty refresh_token fails closed as AUTH_REFRESH_PERSISTENCE_FAILED, leaves the old on-disk credentials untouched, and requires storage/service diagnostics before local reset or re-login. Keep the existing credential files available, run the diagnostics above, and branch only on the structured recovery fields.

Newer builds also include nullable session_recovery metadata on bullpen status --output json and bullpen doctor auth --output json. When it is present, branch on session_recovery.code, requires_login, safe_to_retry, and next_command. session_recovery.code is not the same field as a top-level error code; it uses snake_case values such as auth_login_required and auth_refresh_rejected. Do not start login, forced logout, or file cleanup from prose alone.

Failed device-login and email-verification attempts may also include an auth_incident object. If it reports safe_to_retry: false, follow its auth_incident.next_command exactly as emitted. A bullpen support next command means the attempt needs inspection; do not rewrite that field to a different command. Repeating login or requesting another email code can hide the original state.

For account-level recovery, use the recovery_plan object when bullpen fix --refresh, bullpen recover polymarket --refresh --output json, or bullpen support bundle --output json emits it. For auth-attempt recovery, use auth_incident. Do not infer a reset, forced logout, wallet repair, or support handoff from prose alone. If you need a passive support artifact, optionally run bullpen support bundle --output json. The support bundle includes a root privacy_contract that discloses retained operational identifiers, exact balances, and local paths. It remains local until you attach it to a ticket.

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 that class for support routing; do not ask for raw credential-store error chains.

Example output
$ bullpen doctor auth --output json
{
  "status": "error",
  "error_code": "AUTH_REAUTHENTICATION_REQUIRED",
  "credentials_valid": true,
  "token_valid": false,
  "token_expires_in_secs": null,
  "refresh_token_expires_in_secs": null,
  "credentials_error": null,
  "credential_error_class": null,
  "keypair_checked": false,
  "keypair_valid": false,
  "wallet_ready": false,
  "trade_auth_state": "reauthentication_required",
  "trade_auth_blocked": true,
  "trade_auth_blocker_reason": "No local Bullpen session is available.",
  "turnkey_signing_session_present": true,
  "turnkey_signing_session_expired": true,
  "session_recovery": {
    "state": "login_required",
    "code": "auth_login_required",
    "requires_login": true,
    "safe_to_retry": false,
    "next_command": "bullpen login"
  },
  "remediation": {
    "action": "reauthenticate",
    "command": "bullpen login",
    "message": "Refresh local Bullpen and Turnkey credentials, then retry the real trade."
  },
  "privacy_contract": {
    "schema_version": 1,
    "broad_pii_redaction_claimed": false,
    "credentials_redacted": true,
    "wallet_addresses_included": false,
    "transaction_ids_included": false,
    "order_ids_included": false,
    "trade_ids_included": false,
    "condition_ids_included": false,
    "exact_balances_included": false,
    "account_resource_ids_included": false,
    "local_paths_included": false,
    "raw_provider_bodies_included": false,
    "raw_credential_error_chains_included": false,
    "absolute_local_paths_included": false,
    "support_safe": true
  }
}

If the issue involves a copied headless profile, run the deployment diagnostic from the destination machine too.

bullpen doctor deploy-auth --output json

See the generated doctor deploy-auth reference.

Choose The Recovery Path

Use the smallest recovery action that matches the diagnostic result.

Diagnostic result Next safe action
bullpen status --output json and bullpen doctor auth --output json report login is required, the device code expired, or the browser did not open Run bullpen login or bullpen login --no-browser.
A device-login or email-verification auth_incident says safe_to_retry: false and next_command: "bullpen support" Preserve the exact auth_incident.next_command. If you need a passive support artifact, optionally run bullpen support bundle --output json and attach the generated JSON file. Do not repeat the same auth attempt.
You were away and signing/trading now fails, or turnkey_signing_session_expired is true Run bullpen status --output json and bullpen doctor auth --refresh --output json; run bullpen login only when diagnostics require login. Do not delete ~/.bullpen first.
credentials.json.enc or credential_salt.bin is missing or corrupt Run bullpen login only when diagnostics require a fresh session; it moves unreadable local auth files aside before login. Run bullpen status --output json and bullpen doctor auth --output json first if you need support to inspect copied-home state; use refresh only if support or diagnostics asks for it.
Refresh fails with AUTH_REFRESH_PERSISTENCE_FAILED after a missing or empty returned refresh_token Keep the old credential files untouched and collect bullpen status --output json plus bullpen doctor auth --refresh --output json. Treat it as storage/service diagnostics, not a partial refresh success.
You choose to reset unrecoverable local auth state Run bullpen logout for a normal active-session local reset, or bullpen logout --force only as the last-resort broader local reset. Start a fresh login afterward only when diagnostics require it.
doctor auth says local keypair repair is applicable Save the read-only JSON first, then run bullpen doctor auth --repair --yes without --output json. If destructive repair is applicable, repair is refused with --output json; no-op or not-applicable diagnostics may still return JSON. Destructive repair requires table mode and typing REPAIR; --yes alone does not confirm it.
The command is using the wrong account, environment, or config file Create or inspect an isolated profile with both BULLPEN_HOME and BULLPEN_CONFIG.
A partial copied credential bundle, changed absolute home, or username mismatch is blocking unattended deployment Restore the complete source bundle or run bullpen status --output json plus bullpen doctor auth --output json on the destination machine before any fresh login; do not keep copying partial auth files. Use refresh only if support or diagnostics asks for it.

For copied homes, confirm that credentials.json.enc, credential_salt.bin, and keys/ came from the same source profile. Use the same absolute BULLPEN_HOME and the same BULLPEN_USERNAME_OVERRIDE on both machines, then run bullpen doctor deploy-auth --output json on the destination host before running unattended commands.

Use a local persistent filesystem for copied-home auth. NFS mounts, cloud-synced folders, and container volumes can behave differently from the release environment. Run doctor deploy-auth, status, and doctor auth --refresh on the exact runtime that will use the copied profile; those diagnostics do not guarantee every NFS/cloud-sync/container lock and fsync behavior is safe. If the path, username component, or bundled files differ, run bullpen status --output json plus bullpen doctor auth --output json on the destination host before creating a fresh login there. Do not try to repair copied pieces independently.

Use the generated login, logout, and doctor auth references before running a destructive reset.

For deterministic CI or release smoke runs, set BULLPEN_DISABLE_UPDATE_CHECK=1 before read-only diagnostics. This disables the background update-check cache write only; it does not change credential loading, refresh, or trading behavior.

Isolate A Support Profile

Create a profile that keeps config, credentials, and logs together. This does not touch the default ~/.bullpen profile. This is a non-runnable sequence: run config init only when creating the isolated profile.

export BULLPEN_HOME="$PWD/.bullpen-support-home"
export BULLPEN_CONFIG="$BULLPEN_HOME/config.toml"
mkdir -p "$BULLPEN_HOME"
bullpen config init
bullpen config show --output json

config init writes a local config file in the isolated profile. It does not log in or move funds. If BULLPEN_CONFIG points to a missing file, Bullpen fails closed instead of silently using the default profile.

After config show confirms the expected path, inspect auth state. This is not copy-pasteable as one sequence: log in to that profile only when diagnostics require login.

bullpen status --output json
bullpen doctor auth --output json

After any required login, rerun passive status:

bullpen status --output json

Use --no-browser when the login browser is on a different machine or when you need to copy the device-code URL into an existing browser session, and only after diagnostics require login.

Local Reset Boundaries

Local reset commands only affect files on the current machine and profile. They do not repair server-side account state, wallet routing, missing deposits, or trading permissions.

This is a non-runnable sequence: run normal logout only when the credential store is readable and you intentionally want to clear the active local session.

bullpen logout

State change: This removes the session credentials that logout captured when it started and deletes the local offline signing key when that captured session still matches the active profile. If another login or refresh saves a newer local session first, Bullpen preserves the newer session material instead of deleting it. Normal logout does not delete config, logs, support bundles, installed binaries, or server account/wallet state.

This is a non-runnable sequence: use forced logout only as a last-resort local reset after bullpen login cannot move unreadable local auth aside or support asks for a full local reset.

bullpen logout --force

State change: This clears local auth files for the active profile. Keep bullpen status --output json and bullpen doctor auth --output json output before running it when possible. After forced logout, rerun passive diagnostics and start a fresh login only if diagnostics require it.

When you need a machine-readable reset report for support, use bullpen logout --force --output json. The JSON report returns top-level server_warning and force_wipe fields, redacts local absolute paths, and marks the reset as destructive.

This is a non-runnable sequence: use auth repair only when the diagnostic output names that repair.

bullpen doctor auth --repair --yes

State change: This backs up and removes a corrupt local keypair file when doctor auth says the repair is applicable. It is not the generic fix for missing encrypted credentials or missing salt files. When destructive repair is applicable, it must run in table mode, is refused with --output json, and still requires typing REPAIR at the prompt even when --yes is present. No-op or not-applicable repair diagnostics may still return JSON.

Support Capture

For support tickets, include sanitized output from the failing profile. This is not copy-pasteable as a recovery sequence: run refreshed auth diagnostics only when refreshed evidence is needed for the support case.

bullpen --version
bullpen status --output json
bullpen doctor auth --output json
bullpen config show --output json

If the issue involves copied credentials or a headless host, include:

bullpen doctor deploy-auth --output json

Do not attach secrets, full config files, full logs, credential files, key directories, JWTs, or private keys. Raw logs are exceptional 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. If support needs wallet-routing or funds evidence too, switch to the Wallet Routing And Funds Recovery guide.

See Also