basecamp/kamal · error · RuntimeError
Could not read secrets from Bitwarden Secrets Manager
Error message
Could not read secrets from Bitwarden Secrets Manager
What it means
In list mode (selector `all` or `<project>/all`) the adapter runs `bws secret list` (optionally with a project id); a non-zero exit raises RuntimeError "Could not read secrets from Bitwarden Secrets Manager". This is a bulk-fetch failure: authentication (BWS_ACCESS_TOKEN) was checked earlier via `bws project list`, so the usual causes are project-level access or an invalid project id.
Source
Thrown at lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb:28
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 ]
elsif secrets[0].end_with?(LIST_ALL_FROM_PROJECT_SUFFIX)
project = secrets[0].split(LIST_ALL_FROM_PROJECT_SUFFIX).first
[ "#{LIST_COMMAND} #{project.shellescape}", project ]
end
end
endView on GitHub (pinned to eee0083b38)
Solutions
- Run bws project list to confirm which project ids the token can actually see
- Use a project id from that list in the selector: kamal secrets fetch -a bitwarden-sm <project-id>/all
- In the Bitwarden Secrets Manager web vault, grant the machine account access to the project containing the secrets
- Retry once for transient network errors; upgrade the bws CLI if project list works but secret list errors
Example fix
# before kamal secrets fetch -a bitwarden-sm 3f9a2b1c-xxxx/all # => RuntimeError: Could not read secrets from Bitwarden Secrets Manager # fix (terminal) bws project list # copy a project id you can access kamal secrets fetch -a bitwarden-sm 8d2e4f6a-yyyy/all
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")
projects = JSON.parse(`bws project list`).map { |p| p["id"] }
abort "project #{project_id} not accessible; available: #{projects.join(", ")}" unless projects.include?(project_id) Type guard
def bws_project_accessible?(project_id)
JSON.parse(`bws project list`).any? { |p| p["id"] == project_id }
end Try / catch
begin
adapter.fetch(["#{project_id}/all"])
rescue RuntimeError => e
if e.message.include?("Could not read secrets from Bitwarden Secrets Manager")
warn "run `bws project list` — the machine account may lack access to #{project_id}"
end
raise
end Prevention
- Always take project ids from `bws project list` output for the token in use
- Assign the machine account to the project in the Bitwarden SM web vault before first fetch
- Include a `bws project list` health check at the start of CI pipelines that bulk-fetch secrets
When it happens
Trigger: kamal secrets fetch -a bitwarden-sm all with a token whose machine account has no projects/secrets assigned; `<project-id>/all` where the id is wrong or the machine account lacks access to that project; bws CLI version mismatch; transient API/network failure.
Common situations: Machine account created without project assignments; copying a project id from a different organization; token rotated to an account with narrower scope; network issues on CI runners.
Related errors
- Could not read #{secret_uuid} 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/1f64f7415e2b927e.
Report an issue: GitHub.