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

  1. List what the CLI actually sees: `passbolt list resources --column name --json` (add `--folder <id>` for folder scoping) and copy the exact name.
  2. Correct the reference in deploy.yml so the name and folder path match Passbolt exactly; names are case-sensitive.
  3. In the Passbolt UI, confirm the resource is shared with the user whose GPG key the CLI uses.
  4. 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

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


AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21). Data as JSON: /api/errors/5ba6101e4f13265b. Report an issue: GitHub.