basecamp/kamal · error · RuntimeError
Could not read #{item} from Bitwarden
Error message
Could not read #{item} from Bitwarden What it means
For each requested Bitwarden item the adapter runs `bw get item <name>`; a non-zero exit raises RuntimeError "Could not read <item> from Bitwarden". The command succeeded at the CLI level (session valid) but no item with that exact name/uuid was returned — typically a missing or unsynced item, or a name mismatch.
Source
Thrown at lib/kamal/secrets/adapters/bitwarden.rb:28
if status["status"] == "locked"
session = run_command("unlock --raw", raw: true).presence
status = run_command("status", session: session)
end
raise RuntimeError, "Failed to login to and unlock Bitwarden" unless status["status"] == "unlocked"
run_command("sync", session: session, raw: true)
raise RuntimeError, "Failed to sync Bitwarden" unless $?.success?
session
end
def fetch_secrets(secrets, from:, account:, session:)
{}.tap do |results|
items_fields(prefixed_secrets(secrets, from: from)).each do |item, fields|
item_json = run_command("get item #{item.shellescape}", session: session, raw: true)
raise RuntimeError, "Could not read #{item} from Bitwarden" unless $?.success?
item_json = JSON.parse(item_json)
if fields.any?
results.merge! fetch_secrets_from_fields(fields, item, item_json)
elsif item_json.dig("login", "password")
results[item] = item_json.dig("login", "password")
elsif item_json["fields"]&.any?
fields = item_json["fields"].pluck("name")
results.merge! fetch_secrets_from_fields(fields, item, item_json)
else
raise RuntimeError, "Item #{item} is not a login type item and no fields were specified"
end
end
end
end
def fetch_secrets_from_fields(fields, item, item_json)
fields.to_h do |field|
item_field = item_json["fields"].find { |f| f["name"] == field }View on GitHub (pinned to eee0083b38)
Solutions
- Verify the item resolves: bw get item <name> in the same shell — if it errors, the name or access is wrong
- Run bw sync to pull the latest vault, then retry the fetch
- Use the item's exact name (or its UUID) in the kamal secrets fetch arguments, matching case
- Confirm the logged-in account/organization can see the item in the Bitwarden web vault
Example fix
# before kamal secrets fetch -a bitwarden --account me@example.com MASTER_KEY # => RuntimeError: Could not read MASTER_KEY from Bitwarden # fix (terminal) bw sync bw get item myapp-master-key # find the real name kamal secrets fetch -a bitwarden --account me@example.com myapp-master-key
Defensive patterns
Strategy: validation
Validate before calling
items.each do |item|
ok = system("bw get item #{item.shellescape} > /dev/null 2>&1")
warn "bitwarden item `#{item}` not found/accessible — check name and bw sync" unless ok
end Type guard
def bitwarden_item_exists?(name)
system("bw get item #{name.shellescape} > /dev/null 2>&1")
end Try / catch
begin
secrets = adapter.fetch(names, account: account)
rescue RuntimeError => e
if e.message.include?("from Bitwarden")
names.each { |n| warn "check item: bw get item #{n}" unless system("bw get item #{n.shellescape} > /dev/null 2>&1") }
end
raise
end Prevention
- Run `bw sync` right after creating/renaming items so fetches see them
- Prefer item UUIDs over display names in scripts to survive renames
- Automate the item-exists pre-check in CI for a precise error before deploy
When it happens
Trigger: Requesting secret RAILS_MASTER_KEY when the vault item is named myapp-master-key; item exists in a different organization/collection not accessible; item was created after the last bw sync; requesting with an id instead of the name kamal resolved.
Common situations: Renaming items in the Bitwarden web vault without updating deploy scripts; new teammate whose account lacks access to the organization holding the item; item created moments before fetch on another machine.
Related errors
- Item #{item} is not a login type item and no fields were spe
- Could not find field #{field} in item #{item} in Bitwarden
- Unknown secrets adapter: #{name}
- Failed to login to and unlock Bitwarden
- Failed to sync Bitwarden
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/5e51cd6d2d57b8a2.
Report an issue: GitHub.