Skip to content
Bitbucket app passwords are deprecated and cannot be created. Use API tokens instead. Create an API token.

Troubleshooting

Find your error message below. Errors go to stderr and exit 1, with a prefix (ERR under --no-unicode or BB_NO_UNICODE). Under --json a failure becomes a single-line JSON object on stderr instead. Errors raised before the command runs — unknown command, unknown option — stay plain text with an error: prefix either way.

✗ Authentication required. Run 'bb auth login' or set BB_USERNAME and BB_API_TOKEN.

No credentials are stored — you have not logged in, or bb auth logout cleared them.

Terminal window
bb auth login

✗ OAuth token expired. Run 'bb auth login' to re-authenticate.

The refresh token was revoked or expired, or the OAuth consumer was deleted.

Terminal window
bb auth logout
bb auth login

bb auth login reports a rejected API token like this:

✗ Invalid username or token: Unauthorized. Verify your Bitbucket username and that the API token is current and has the required scopes.

On any other command a 401 shows Bitbucket’s own message plus a dimmed remediation line:

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

If you authenticated with OAuth, re-authenticate:

Terminal window
bb auth logout
bb auth login

If you use an API token, mint a fresh one at Bitbucket API Tokens — scopes cannot be added to an existing token — then log in again, keeping the token out of shell history:

Terminal window
echo "$BB_API_TOKEN" | bb auth login -u myuser --with-token

The most common cause is environmental, not network:

  • BB_API_TOKEN is exported in your shell. Its mere presence — even set to an empty string — selects API-token auth and skips OAuth entirely. Run unset BB_API_TOKEN and retry. (-u, -p, --app-password, and --with-token select the same path, deliberately.)
  • SSH session, headless machine, or WSL without browser integration.
  • No default browser configured.

When the browser cannot be opened, bb prints the authorization URL to stderr — copy it into any browser and the flow completes normally. Or skip OAuth:

Terminal window
bb auth login -u myuser -p your-api-token

✗ Port 19872 is already in use. Close the application using it and try again.

The OAuth callback server binds 127.0.0.1:19872 and waits up to 5 minutes.

Terminal window
lsof -i :19872 # macOS/Linux

Close the other bb auth login (or whatever holds the port) and retry.


Token works in the browser but not in the CLI

Section titled “Token works in the browser but not in the CLI”
  1. Confirm it is an API token, minted at Bitbucket API Tokens. App passwords live at a different URL and are deprecated.

  2. Check the scopes cover what you are running — see Token Scopes. A missing scope surfaces as a 403 with the hint Your token may be missing a required scope.

  3. Strip whitespace when pasting:

    Terminal window
    # Good - token only
    bb auth login -u myuser -p ATBB_xxxxx
    # Bad - leading space inside the quotes
    bb auth login -u myuser -p " ATBB_xxxxx"

✗ Config file has insecure permissions (644); expected 600. Run: chmod 600 /home/me/.config/bb/config.json

On macOS and Linux, bb refuses to read a config file or directory that is readable by group or other. This usually follows copying a config between machines or restoring a dotfiles repository. Windows skips the check.

Terminal window
chmod 700 ~/.config/bb
chmod 600 ~/.config/bb/config.json

A hand-edited file that no longer parses gives:

✗ Config file is not valid JSON: /home/me/.config/bb/config.json. Fix the file by hand or remove it and run `bb auth login` again.

Both are error code 4001 (CONFIG_READ_FAILED).


✗ Could not determine repository. Use --workspace and --repo options, or run this command from within a Bitbucket repository.

Three sibling messages name the specific reason:

✗ Not in a git repository. Use --workspace and --repo options, or run this command from within a Bitbucket repository.
✗ Git repository has no remote configured. Add a Bitbucket remote with `git remote add origin <url>`, or use --workspace and --repo options, or run this command from within a Bitbucket repository.
✗ Remote 'git@github.com:me/thing.git' is not a Bitbucket URL. Use --workspace and --repo options, or run this command from within a Bitbucket repository.

All four are code 6001 (CONTEXT_REPO_NOT_FOUND). Pick whichever fix suits:

Terminal window
bb pr list -w myworkspace -r myrepo # explicit flags
bb config set defaultWorkspace myworkspace
cd /path/to/cloned-bitbucket-repo && bb pr list

See Repository Context for the full precedence rules.


Commands that know what they were looking for name it, and stop there:

✗ Repository my-ws/typo not found.
✗ Pull request #999 not found in my-ws/my-repo.

Everywhere else a 404 surfaces Bitbucket’s own message with a dimmed remediation line appended — see Failures that tell you the next step. In --json mode that line arrives as a top-level hint string on the error envelope.

Usual causes: a typo in the workspace or repository slug, a repository you have no access to, or one that was renamed. To check what you can actually see:

Terminal window
bb workspace list
bb repo list -w myworkspace

✗ 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.
Terminal window
curl -I https://api.bitbucket.org # connectivity
export HTTPS_PROXY=http://proxy.example.com:8080
DEBUG=true bb repo list # [HTTP] tracing on stdout, secrets redacted

Bitbucket’s own availability is at status.bitbucket.org.


✗ 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.

The per-request timeout defaults to 30000 ms.

Terminal window
BB_HTTP_TIMEOUT=60000 bb pr list # 60 seconds
BB_HTTP_TIMEOUT=0 bb pr list # no timeout

A 429 is retried automatically. In human mode you see the attempts on stderr:

⚠ Rate limited, retrying in 1.0s (attempt 1/3)...

Retries cover HTTP 429, 502, 503, and 504, up to 3 attempts. On a 429 the Retry-After header sets the delay when Bitbucket sends one; otherwise the delay is exponential backoff from 1s. Transient network failures on GET, HEAD, and OPTIONS share the same 3-attempt budget. Once it is exhausted, the command fails with Bitbucket’s own 429 message.

The retry warning is suppressed in --json mode, so scripts see only the final failure.

If the limit is sustained:

  1. Wait a few minutes and retry.

  2. Add a delay between calls in loops:

    Terminal window
    for pr_id in 1 2 3 4 5; do
    bb pr view $pr_id
    sleep 1
    done
  3. Fetch once and filter locally instead of calling per item:

    Terminal window
    bb pr list --json --jq '.pullRequests[] | select((.author.nickname // .author.display_name) == "alice")'

bb repo clone shells out to git clone git@bitbucket.org:<workspace>/<repo>.git, so the error text is git’s own, verbatim:

✗ git@bitbucket.org: Permission denied (publickey).

That is an SSH problem, not a bb auth problem — the CLI does not pass its token to git.

Terminal window
ssh -T git@bitbucket.org # verify your key
git clone https://bitbucket.org/myworkspace/myrepo.git # HTTPS fallback

✗ This will permanently delete myworkspace/old-repo.
Use --yes to confirm.

The -y, --yes help text says “Skip confirmation prompt”, but there is no prompt — the command fails until you pass the flag. This affects bb repo delete, bb repo default-reviewers remove, bb pr comments delete, bb snippet delete, and bb snippet comments delete.

Terminal window
bb repo delete myworkspace/old-repo --yes

A missing title is caught locally, before any request:

✗ Pull request title is required. Use --title option.

Everything else is Bitbucket’s own message, with any error.fields detail flattened in — for example:

✗ Bad request (type: extra keys not allowed)
Cause Fix
Branch doesn’t exist on remote git push -u origin your-branch
PR already exists for branch Check bb pr list
Branch restrictions block the destination Check repository settings
No changes between branches Ensure commits exist

Bitbucket returns the reason in the error message. Diagnose the rest without leaving the terminal:

Terminal window
bb pr checks 42 # failing builds
bb pr view 42 # reviewer approvals and merge state
bb pr activity 42 # who requested changes

Common blockers are merge conflicts, unmet required approvals, and failing build checks. Fall back to the web UI only for branch-restriction rules, which the API does not expose.


Terminal window
bb pr diff 42
# (empty output)

The PR has no file changes, or the API returned an empty diff.

Terminal window
bb pr view 42 # check state and branches
bb pr diff 42 --web # compare against the web UI

bb suggests a correction when a command name or an option value is close to a valid one:

Terminal window
bb prr
# ✗ unknown command 'prr'
# (Did you mean pr?)
bb pr lst
# error: unknown command 'lst'
# (Did you mean list?)
bb pr list --state opne
# ✗ --state must be one of: OPEN, MERGED, DECLINED, SUPERSEDED
# (Did you mean OPEN?)

Option values are matched case-sensitively, so --state open (lowercase against an uppercase set) tells you to fix the case rather than suggesting the same word back:

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

Use bb help <command> (or bb <command> --help) to see a command’s valid values.

--json takes an optional field list, so it swallows the next word if you put it first:

Terminal window
bb --json pr list

--json did parse, so the failure comes back as a JSON envelope on stderr:

{"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"}

bb --json=id,title pr list works, because the --flag=value form does not eat the next token.

Terminal window
bb pr list --jq '.pullRequests[].title'
# ✗ --jq requires --json

Because --json was never set, this failure renders as plain text on stderr, not as a JSON envelope — surprising in a script that only parses stdout. bb api is the one exception: it accepts --jq on its own.

Terminal window
bb pr list --json --jq '.pullRequests[].title' # correct
bb api /repositories/my-ws --jq '.values[].name' # allowed without --json
Terminal window
bb pr list --json ""
{"name":"BBError","code":8002,"message":"--json field list cannot be empty"}

--json ,, fails the same way. Use bare --json for the full envelope.


401, 403, and 404 failures append an actionable line beneath the error:

Terminal window
bb repo list -w does-not-exist
# ✗ No workspace with identifier 'does-not-exist'.
# Verify the id or slug you passed, and that --workspace/--repo point at the right repository your token can see.

A 401 points you at bb auth login; a 403 explains that scopes can’t be added to an existing token and links Token Scopes. In --json mode the same text arrives as a hint field. See Error codes for the full list.


When reporting an issue, gather this:

Terminal window
# CLI version
bb --version
# OS information
uname -a # Linux/macOS
systeminfo | findstr /B /C:"OS" # Windows
# Bun version (required runtime)
bun --version
# Auth status (never prints the token; use bb auth token for that)
bb auth status
# Config (masks secrets)
bb config list

bb auth status makes a live GET /user call, so it also fails when the network or proxy is the real problem.


  1. Check the FAQ for questions that come up often
  2. Search existing issues
  3. Open a new issue with:
    • CLI version (bb --version)
    • Operating system
    • Complete error message
    • Steps to reproduce