basecamp/kamal · error · RuntimeError
Could not read #{secret_uuid} from Bitwarden Secrets Manager
Error message
Could not read #{secret_uuid} from Bitwarden Secrets Manager What it means
In UUID-get mode the adapter runs `bws secret get <uuid>`; a non-zero exit raises RuntimeError "Could not read <uuid> from Bitwarden Secrets Manager". Authentication for bws comes from the BWS_ACCESS_TOKEN environment variable (the adapter has no account concept — requires_account? is false), so a bad token is a common root cause, as is an incorrect UUID.
Source
Thrown at lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb:22
end
private
LIST_ALL_SELECTOR = "all"
LIST_ALL_FROM_PROJECT_SUFFIX = "/all"
LIST_COMMAND = "secret list"
GET_COMMAND = "secret get"
def fetch_secrets(secrets, from:, account:, session:)
raise RuntimeError, "You must specify what to retrieve from Bitwarden Secrets Manager" if secrets.length == 0
secrets = prefixed_secrets(secrets, from: from)
command, project = extract_command_and_project(secrets)
{}.tap do |results|
if command.nil?
secrets.each do |secret_uuid|
item_json = run_command("#{GET_COMMAND} #{secret_uuid.shellescape}")
raise RuntimeError, "Could not read #{secret_uuid} from Bitwarden Secrets Manager" unless $?.success?
item_json = JSON.parse(item_json)
results[item_json["key"]] = item_json["value"]
end
else
items_json = run_command(command)
raise RuntimeError, "Could not read secrets from Bitwarden Secrets Manager" unless $?.success?
JSON.parse(items_json).each do |item_json|
results[item_json["key"]] = item_json["value"]
end
end
end
end
def extract_command_and_project(secrets)
if secrets.length == 1
if secrets[0] == LIST_ALL_SELECTOR
[ LIST_COMMAND, nil ]View on GitHub (pinned to eee0083b38)
Solutions
- Verify the token works at all: bws project list — if it fails, fix BWS_ACCESS_TOKEN first
- Reproduce the get: bws secret get <uuid> and check the error output
- Copy the full secret UUID from the Bitwarden Secrets Manager web vault (Projects → Secrets) and retry with the exact value
- If access was revoked, reissue a token for the machine account with access to the relevant project
Example fix
# before kamal secrets fetch -a bitwarden-sm 5c8e8d3a-xxxx # => RuntimeError: Could not read 5c8e8d3a-xxxx from Bitwarden Secrets Manager # fix (terminal) export BWS_ACCESS_TOKEN=<machine-account-token> bws secret get 5c8e8d3a-xxxx-xxxx-xxxx-xxxxxxxxxxxx # verify exact uuid works kamal secrets fetch -a bitwarden-sm 5c8e8d3a-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Defensive patterns
Strategy: try-catch
Validate before calling
abort "BWS_ACCESS_TOKEN not set or invalid" unless system("bws project list > /dev/null 2>&1")
uuids.each do |uuid|
warn "#{uuid} unreadable — check id and access" unless system("bws secret get #{uuid.shellescape} > /dev/null 2>&1")
end Type guard
def bws_secret_readable?(uuid)
system("bws secret get #{uuid.shellescape} > /dev/null 2>&1")
end Try / catch
begin
adapter.fetch([uuid])
rescue RuntimeError => e
if e.message.include?("from Bitwarden Secrets Manager")
abort "check BWS_ACCESS_TOKEN and run: bws secret get #{uuid}"
end
raise
end Prevention
- Export BWS_ACCESS_TOKEN in every automation environment; verify with `bws project list` first
- Store secret UUIDs alongside the pipeline (not hand-typed) to avoid truncation
- When rotating machine-account tokens, update the stored token the same day to avoid cryptic get failures
When it happens
Trigger: BWS_ACCESS_TOKEN unset, expired, or revoked; the machine account's token lacks access to that secret; malformed or truncated UUID; secret deleted from the project.
Common situations: CI not exporting BWS_ACCESS_TOKEN; rotating the machine-account token but not updating the CI variable; copy-pasting UUIDs with missing characters; secret moved between projects.
Related errors
- Could not read secrets from Bitwarden Secrets Manager
- Could not authenticate to Bitwarden Secrets Manager. Did you
- Failed to login to and unlock Bitwarden
- Failed to sync Bitwarden
- Could not read #{item} from Bitwarden
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/2c337a320b9a4928.
Report an issue: GitHub.