basecamp/kamal · error · RuntimeError
Could not find the following secrets in Passbolt: #{missing_
Error message
Could not find the following secrets in Passbolt: #{missing_secrets.join(", ")} What it means
After the passbolt CLI successfully returns a JSON resource list, the adapter compares the requested secret names against each item's "name" field (passbolt.rb:55). This error fires when one or more requested names are absent from the results, and the message lists them. The CLI worked; the name/folder combination you referenced simply does not match any readable resource.
Source
Thrown at lib/kamal/secrets/adapters/passbolt.rb:55
current_folder = matching_folders.first if matching_folders.any?
end
if current_folder
filter_conditions << "(Name == #{secret_name.shellescape.inspect} && FolderParentID == #{current_folder["id"].shellescape.inspect})"
end
else
# for root level secrets (no folders)
filter_conditions << "Name == #{secret_name.shellescape.inspect}"
end
end
filter_condition = filter_conditions.any? ? "--filter '#{filter_conditions.join(" || ")}'" : ""
items = `passbolt list resources #{filter_condition} #{folders.map { |item| "--folder #{item["id"].to_s.shellescape}" }.join(" ")} --column name --column password --json`
raise RuntimeError, "Could not read #{secrets} from Passbolt" unless $?.success?
items = JSON.parse(items)
found_names = items.map { |item| item["name"] }
missing_secrets = secret_names - found_names
raise RuntimeError, "Could not find the following secrets in Passbolt: #{missing_secrets.join(", ")}" if missing_secrets.any?
items.to_h { |item| [ item["name"], item["password"] ] }
end
def secrets_get_folders(secrets)
# extract all folder paths (both parent and nested)
folder_paths = secrets
.select { |s| s.include?("/") }
.map { |s| s.split("/")[0..-2] } # get all parts except the secret name
.uniq
return [] if folder_paths.empty?
all_folders = []
# first get all top-level folders
parent_folders = folder_paths.map(&:first).uniq
filter_condition = "--filter '#{parent_folders.map { |name| "Name == #{name.shellescape.inspect}" }.join(" || ")}'"View on GitHub (pinned to eee0083b38)
Solutions
- List what the CLI actually sees: `passbolt list resources --column name --json` (add `--folder <id>` for folder scoping) and copy the exact name.
- Correct the reference in deploy.yml so the name and folder path match Passbolt exactly; names are case-sensitive.
- In the Passbolt UI, confirm the resource is shared with the user whose GPG key the CLI uses.
- If the secret lives at root, reference it without folder segments, or move it into the folder the config expects.
Example fix
// before # deploy.yml secrets: - DB_PASSWORD=passbolt/infra/prod/db_password # wrong folder path // after secrets: - DB_PASSWORD=passbolt/infra/db_password # exact Name shown by `passbolt list resources`
Defensive patterns
Strategy: validation
Validate before calling
# Verify every referenced secret exists before deploying
required = %w[db_password api_token]
available = JSON.parse(`passbolt list resources --json`).map { |r| r["name"] }
missing = required - available
abort "Missing in Passbolt: #{missing.join(', ')}" if missing.any? Try / catch
begin
# task resolving passbolt/* secrets
rescue RuntimeError => e
if e.message =~ /Could not find the following secrets in Passbolt/
abort "#{e.message} — cross-check `passbolt list resources --column name --json`"
else
raise
end
end Prevention
- Copy secret names from `passbolt list resources` output, never from memory
- Keep names in Passbolt and deploy.yml under one review process so renames stay in sync
- After moving a resource between folders, grep deploy.yml for stale paths
- Names are case-sensitive — review casing in references
When it happens
Trigger: A secret reference like `passbolt/folder/SUBFOLDER/SECRET_NAME` in Kamal config where SECRET_NAME does not exist at that path, exists under a different folder or at root, is misspelled or has different casing, or is not shared with the Passbolt user the CLI authenticates as (unshared resources are simply absent from `list resources` output).
Common situations: Typo or wrong case in the secret name; the secret was moved to another folder but deploy.yml still references the old path; a root-level secret referenced with a folder prefix or vice versa; Passbolt permissions not granted to the CLI user or its group; trailing whitespace in the resource name.
Related errors
- Could not find #{missing_items.join(", ")} in LastPass
- Failed to login to Passbolt
- No secrets given to fetch
- Could not read #{secrets} from Passbolt
- Could not find the following folders in Passbolt: #{missing_
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/5ba6101e4f13265b.
Report an issue: GitHub.