Skip to content

Error Codes

Every failure carries a numeric code in the --json error payload ({"code": 2002, …}). The process exit status is always 1, so branch on code, not on the exit status. Ctrl-F the number below.

Range Category Description
1xxx Authentication Login, credentials, and token issues
2xxx API Bitbucket API request failures
3xxx Git Local git operations
4xxx Configuration Config file read/write issues
5xxx Validation Invalid input or missing required fields
6xxx Context Repository/workspace detection issues
7xxx Network Transport/network failures before API response
8xxx Output formatting --json fields and --jq evaluation issues
9xxx Shell completion / Unknown Completion install/uninstall failures and uncategorized errors

Message: Authentication required

Cause: You haven’t logged in yet, or your credentials have been cleared.

Solution:

Terminal window
bb auth login

Message: Invalid credentials

Cause: Your credentials were rejected by Bitbucket at request time. This is the code emitted for any 401 response that was not recovered by an OAuth refresh — e.g. a wrong API token, a revoked password, or basic-auth requests with bad credentials.

Solution:

  1. Verify your Bitbucket username
  2. Generate a new API token at Bitbucket API Tokens
  3. Re-authenticate:
Terminal window
bb auth logout
bb auth login

The CLI prints this next step alongside the error:

Your Bitbucket credentials were rejected. Run bb auth login to re-authenticate.

Message: OAuth token expired. Run bb auth login to re-authenticate.

Cause: Specifically: an OAuth access token expired and the reactive refresh attempt also failed (refresh token revoked or expired). For non-OAuth flows, a stale token surfaces as AUTH_INVALID (1002) instead.

Solution:

  1. Re-run bb auth login to perform a fresh OAuth flow
  2. If that also fails, create a new API token in Bitbucket settings and switch auth methods

Message: API request failed

Cause: Bitbucket answered with an unexpected HTTP status below 500 that isn’t 401/403/404/429 — typically 400 (malformed request body) or 409 (conflict, e.g. merging a pull request that is already merged). The server did respond, so this is not a connectivity problem.

Solution: Read message and response in the JSON error payload; they carry Bitbucket’s own explanation.

Terminal window
bb pr merge 42 --json 2> err.json
jq '.statusCode, .message, .response' err.json

Connection failures are 7001; server faults are 2005.

Message: Resource not found

Cause: The requested repository, PR, or resource doesn’t exist.

Solution:

  • Check spelling of workspace and repository names
  • Verify the resource exists in Bitbucket
  • Ensure you have access to the repository

Where the message doesn’t already name the missing resource, the CLI appends:

Verify the id or slug you passed, and that –workspace/–repo point at the right repository your token can see.

The hint is omitted when the message is already specific (for example Pull request 999 not found in acme/demo.) and for bb api, where you supplied the URL yourself.

Message: Access denied

Cause: Your API token doesn’t have the required permissions.

Solution:

  1. Check your API token scopes at Bitbucket API Tokens
  2. See Token Scopes for the exact scope each bb command requires.
  3. If a scope is missing, mint a new token (you can’t add scopes to an existing one) and re-authenticate with bb auth login.

The CLI prints this next step alongside the error:

Your token may be missing a required scope. Scopes can’t be added to an existing token — mint a new one, then run bb auth login.

Docs: https://bitbucket-cli.paulvanderlei.com/reference/token-scopes/

A 403 can also be a plain permission denial rather than a scope problem — the API doesn’t distinguish the two, hence the hedged wording.

Message: Rate limit exceeded

Cause: Bitbucket returned 429 and the CLI’s three automatic retries — which honour the Retry-After header — were all exhausted.

Solution: Reduce request volume. Prefer --limit over --all, and batch with bb api --paginate instead of looping single calls:

Terminal window
bb pr list --limit 25 --json
bb api /repositories/myworkspace/myrepo/pullrequests --paginate --json

Message: Bitbucket server error

Cause: Bitbucket’s servers are experiencing issues.

Solution:


Reserved. No code path currently emits 3001 — running outside a git repository surfaces as 6001 CONTEXT_REPO_NOT_FOUND. Don’t branch on 3001 in scripts.

Message: Git command failed

Cause: A git operation (clone, fetch, checkout) failed.

Solution:

  • Ensure git is installed and in your PATH
  • Check git error message for details
  • Verify you have proper SSH keys or credentials configured

Message: No Bitbucket remote found

Cause: The repository has no remote pointing to Bitbucket.

Solution:

  • Add a Bitbucket remote:
Terminal window
git remote add origin git@bitbucket.org:workspace/repo.git
  • Or use explicit flags: -w <workspace> -r <repo>

Message: Cannot read config file

Cause: The configuration file is corrupted or unreadable.

Solution:

  1. Check file permissions
  2. If corrupted, delete and recreate:
Terminal window
# macOS/Linux
rm ~/.config/bb/config.json
bb auth login
# Windows
del %APPDATA%\bb\config.json
bb auth login

Message: Cannot write config file

Cause: No write permission to the config directory.

Solution:

  • Check directory permissions
  • Ensure the parent directory exists
  • On shared systems, verify you own the config directory

Message: Invalid configuration key

Cause: Attempted to get or set an unknown configuration key.

Solution: Use a valid key. bb config set accepts four:

Key Meaning
defaultWorkspace Workspace used when -w is omitted
skipVersionCheck Disable update notifications
versionCheckInterval Days between update checks
prCreateIncludeDefaultReviewers Add the repository’s default reviewers on bb pr create

bb config get accepts those four plus username.

Terminal window
bb config set defaultWorkspace myworkspace
bb config get username
bb config list

Two keys get a distinct message instead of the unknown-key one. bb config set username and bb config set apiToken point you at bb auth login; bb config get apiToken points you at bb auth token. Every other credential field (oauthAccessToken and friends) is not a config key at all and falls through to the unknown-key message above.


Message: Required field missing

Cause: A required option or argument was not provided.

Solution: Check command help for required options:

Terminal window
bb <command> --help

Common required fields:

  • bb pr create requires --title
  • bb repo create requires a name argument

Message: Invalid value

Cause: A provided value doesn’t match expected format, or an unknown top-level command was given.

Solution:

  • Check the expected format in command help
  • Common issues:
    • Pull request ID must be a number
    • State must be one of: OPEN, MERGED, DECLINED, SUPERSEDED
    • An unknown command (bb prr)
    • --json placed before the subcommand, so it ate the subcommand as its field list — see Troubleshooting

The misplaced---json case names the token it swallowed. Because --json did take effect, it comes back as an error envelope on stderr:

Terminal window
bb --json pr list
{"name":"BBError","code":5002,"message":"--json consumed 'pr' as its field list, so 'list' was parsed as a top-level command.\nPut --json after the subcommand: bb pr list --json","context":{"command":"pr","args":["list"]}}

When a value or name is close to a valid one, the CLI suggests the correction. This fires for unknown commands, enum option values, config keys, bb pr activity --type tokens, and bb api HTTP methods:

Terminal window
bb prr
# ✗ unknown command 'prr'
# (Did you mean pr?)
bb pr list --state opne
# ✗ --state must be one of: OPEN, MERGED, DECLINED, SUPERSEDED
# (Did you mean OPEN?)
bb config set defaultWorkspce foo
# ✗ Unknown config key 'defaultWorkspce'. Valid keys: defaultWorkspace, skipVersionCheck, versionCheckInterval, prCreateIncludeDefaultReviewers
# (Did you mean defaultWorkspace?)

Enum values are matched case-sensitively, so a value that is right apart from its case gets a distinct message rather than a suggestion:

Terminal window
bb pr list --state open
# ✗ --state must be one of: OPEN, MERGED, DECLINED, SUPERSEDED
# (Values are case-sensitive — use OPEN.)

Message: File not found: <path>

Cause: A file referenced by an option (--file on bb snippet create/edit, --body-file on bb pr edit, -F key=@file or --input on bb api) doesn’t exist on disk, or a named file isn’t present inside a snippet.

Solution:

  • Verify the path is correct relative to the current working directory
  • For bb snippet view --file <name>, list snippet files first to confirm the name

The context field carries the offending path, so scripts can tell this apart from a generic VALIDATION_INVALID. The key depends on the command:

Key Set by
file bb snippet create/edit/view
bodyFile bb pr edit --body-file only
path bb api -F key=@file, bb api --input <file>

bb snippet view --file also attaches available, the list of filenames the snippet actually contains.

bb pr edit --body-file only reports 5003 when the read failed with ENOENT. Any other read failure (a permission error, or pointing at a directory) is reported as 9999 UNKNOWN.


Message: Could not determine repository

Cause: The CLI couldn’t figure out which repository to use.

Solution:

  1. Use explicit flags:
Terminal window
bb pr list -w myworkspace -r myrepo
  1. Set a default:
Terminal window
bb config set defaultWorkspace myworkspace
  1. Run from within a cloned Bitbucket repository

See Understanding Repository Context for details.

Message: Could not determine workspace

Cause: The CLI couldn’t figure out which workspace to use.

Solution:

  1. Use the -w flag:
Terminal window
bb repo list -w myworkspace
  1. Set a default workspace:
Terminal window
bb config set defaultWorkspace myworkspace

Cause: The request failed before an HTTP response was received (offline, DNS issue, proxy/TLS issue, etc.).

Transient failures (dropped connections, temporary DNS errors, timeouts) on read requests are automatically retried up to 3 times with exponential backoff before this error surfaces. Permanent-looking failures (e.g. unknown host, connection refused) and write requests fail immediately.

7001 has two distinct messages. The connectivity one:

Network error: Unable to reach Bitbucket API. Run with DEBUG=true for details. If you’re behind a proxy or using a custom CA, check your environment.

And the timeout one, when the server accepted the connection but never answered:

Network error: Request to Bitbucket API timed out after 30000ms. The server accepted the connection but did not respond in time. Increase or disable the timeout via BB_HTTP_TIMEOUT (milliseconds; set BB_HTTP_TIMEOUT=0 to disable), or run with DEBUG=true for details.

Solution:

  • Check internet and DNS connectivity
  • Verify proxy/TLS settings if applicable
  • If the message says timed out, raise or remove the 30-second default:
Terminal window
BB_HTTP_TIMEOUT=60000 bb pr list # 60 seconds
BB_HTTP_TIMEOUT=0 bb pr list # no timeout

See Environment Variables for the full list.


Message: jq evaluation failed: <jq compiler error>

Cause: The expression passed to --jq is invalid or produced a runtime error.

Solution:

  • Test the expression interactively against the full output first:
Terminal window
bb pr list --json | jq '<expression>'
  • The embedded jq is jq 1.8.x; module imports (include, import) are not supported.
  • Remember --jq runs after field projection — when combined with --json fields, the input is already a flat array (the wrapper has been dropped).

8002 has exactly two messages.

--jq requires --json — add --json, with or without a field list:

Terminal window
bb pr list --json --jq '.count'

bb api is exempt, because its output is already JSON: bb api /repositories/my-ws --jq '.values[].name' needs no --json.

This one prints as plain text on stderr (✗ --jq requires --json) rather than as a JSON envelope, because JSON mode was never enabled — scripts cannot parse .code for it.

--json field list cannot be empty — triggered by --json "" or --json ,,,. Drop the argument to get the full output, or name at least one field:

Terminal window
bb pr list --json
bb pr list --json id,title

Message: Failed to install completions: <reason>

Cause: bb completion install couldn’t write the shell completion hooks — typically because the target shell profile isn’t writable, or the underlying tabtab install failed.

Solution:

  • Check write permissions on your shell rc file (e.g. ~/.zshrc, ~/.bashrc)
  • Re-run with DEBUG=true bb completion install for the underlying error
  • If the issue persists, install completions manually by following your shell’s documentation for tabtab

Message: Failed to uninstall completions: <reason>

Cause: bb completion uninstall couldn’t remove the completion hooks — usually because the rc file isn’t writable or the entry was already removed manually.

Solution:

  • Check write permissions on your shell rc file
  • Manually remove the tabtab block from your shell rc file if needed

Message: An unexpected error occurred

Cause: The CLI encountered an error that doesn’t fit any known category.

Solution:

  • Check the error message for details
  • Retry the command
  • If the issue persists, report it with full debug output:
Terminal window
DEBUG=true bb <your-command> 2>&1

0 on success, 1 on any failure. The exit status never carries the error code — read it from the stderr payload instead:

Terminal window
bb pr view 999 --json 2> err.json || jq -r '.code' err.json
# 2002

That payload is a single-line JSON object:

{"name":"APIError","code":2002,"message":"Pull request 999 not found in acme/demo.","context":{"status":404,"method":"GET","url":"/repositories/acme/demo/pullrequests/999"},"statusCode":404}

See Exit Codes in the scripting guide for a worked example, and JSON Output for every payload field and the context shape per code.

Keep stdout and stderr on separate files. Folding stderr into the data file (> prs.json 2>&1) puts the error envelope — and any warning the CLI prints — inside prs.json, which breaks jq on the next line.

#!/bin/bash
set -euo pipefail
if ! bb pr list -w myworkspace -r myrepo --json > prs.json 2> pr-error.json; then
echo "Failed to list PRs: $(jq -r '.message // "unknown error"' pr-error.json)"
exit 1
fi
jq -r '.pullRequests[].title' prs.json