basecamp/kamal · error · RuntimeError

Could not read folders from Passbolt

Error message

Could not read folders from Passbolt

What it means

When secret references contain folder paths (e.g. passbolt/parent/nested/NAME), the adapter first resolves folders by running `passbolt list folders --filter '...' --json`. This error (passbolt.rb:75) is raised when that command exits non-zero. It is a CLI/session-level failure of the folder listing, not a 'folder does not exist' condition — genuinely missing folders produce the separate error at line 106.

Source

Thrown at lib/kamal/secrets/adapters/passbolt.rb:75

      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(" || ")}'"
      fetch_folders = `passbolt list folders #{filter_condition} --json`
      raise RuntimeError, "Could not read folders from Passbolt" unless $?.success?

      parent_folder_items = JSON.parse(fetch_folders)
      all_folders.concat(parent_folder_items)

      # get nested folders for each parent
      folder_paths.each do |path|
        next if path.size <= 1 # skip non-nested folders

        parent = path[0]
        parent_folder = parent_folder_items.find { |f| f["name"] == parent }
        next unless parent_folder

        # for each nested level, get the folders using the parent's ID
        current_parent = parent_folder
        path[1..-1].each do |folder_name|
          filter_condition = "--filter 'Name == #{folder_name.shellescape.inspect} && FolderParentID == #{current_parent["id"].shellescape.inspect}'"
          fetch_nested = `passbolt list folders #{filter_condition} --json`
          next unless $?.success?

View on GitHub (pinned to eee0083b38)

Solutions

  1. Run `passbolt list folders --json` manually to see the CLI's own error message.
  2. Re-authenticate or repair the CLI config (`passbolt configure`), the same as for resource read failures.
  3. Rename folders whose names contain quotes or backslashes, or avoid referencing them from Kamal.
  4. Check that the installed CLI version supports `list folders --filter ... --json`.
Defensive patterns

Strategy: try-catch

Validate before calling

# Preflight folder listing when any secret reference contains a slash
`passbolt list folders --json 2>/dev/null`
abort('Passbolt folder listing failed') unless $?.success?

Try / catch

begin
  # task resolving passbolt/folder/... secrets
rescue RuntimeError => e
  if e.message =~ /Could not read folders from Passbolt/
    abort "#{e.message} — diagnose with: passbolt list folders --json"
  else
    raise
  end
end

Prevention

When it happens

Trigger: Any secrets fetch that includes at least one slash-containing passbolt reference while `passbolt list folders --filter '...' --json` fails: an unauthenticated or expired CLI session, an unreachable Passbolt server, or a filter string the CLI rejects (for example folder names containing quotes or backslashes that break the interpolated single-quoted --filter argument).

Common situations: The same auth/config issues as resource listing, but only hit once folder-scoped secrets are used; folder names with shell metacharacters; a passbolt CLI version whose `list folders` flags differ from what the adapter passes.

Related errors


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