basecamp/kamal · error · RuntimeError

Could not find the following folders in Passbolt: #{missing_

Error message

Could not find the following folders in Passbolt: #{missing_paths.join(", ")}

What it means

After fetching parent and nested folders, the adapter rebuilds each folder's full path via get_folder_path and diffs it against the paths implied by your secret references (passbolt.rb:106). The error fires when some expected path such as 'infra/nested' never appears: either the folder genuinely does not exist under that exact hierarchy, or the traversal stopped early because an intermediate lookup returned nothing (the nested loop breaks silently on empty results, and a wrong same-named parent can dead-end the chain).

Source

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

        # 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?

          nested_folders = JSON.parse(fetch_nested)
          break if nested_folders.empty?

          all_folders.concat(nested_folders)
          current_parent = nested_folders.first
        end
      end

      # check if we found all required folders
      found_paths = all_folders.map { |f| get_folder_path(f, all_folders) }
      missing_paths = folder_paths.map { |path| path.join("/") } - found_paths
      raise RuntimeError, "Could not find the following folders in Passbolt: #{missing_paths.join(", ")}" if missing_paths.any?

      all_folders
    end

    def get_folder_path(folder, all_folders, path = [])
      path.unshift(folder["name"])
      return path.join("/") if folder["folder_parent_id"].to_s.empty?

      parent = all_folders.find { |f| f["id"] == folder["folder_parent_id"] }
      return path.join("/") unless parent

      get_folder_path(parent, all_folders, path)
    end

    def check_dependencies!
      raise RuntimeError, "Passbolt CLI is not installed" unless cli_installed?
    end

View on GitHub (pinned to eee0083b38)

Solutions

  1. Run `passbolt list folders --json` and confirm the exact parent-to-child chain; names are case-sensitive.
  2. Fix the path segments in deploy.yml's passbolt references so they mirror the real hierarchy.
  3. Grant the CLI user read access to every folder along the path, not just the leaf.
  4. Rename duplicate or oddly named folders to unique, simple names so resolution is unambiguous.

Example fix

// before
secrets:
  - TOKEN=passbolt/infra/prod/api_token   # 'prod' is not under 'infra'

// after
secrets:
  - TOKEN=passbolt/prod/api_token          # matches the actual folder chain
Defensive patterns

Strategy: validation

Validate before calling

# Rough preflight: every folder segment referenced must exist
segments = %w[infra prod]
names = JSON.parse(`passbolt list folders --json`).map { |f| f["name"] }
missing = segments.uniq - names
abort "Missing folders in Passbolt: #{missing.join(', ')}" if missing.any?

Prevention

When it happens

Trigger: Referencing passbolt/parent/nested/SECRET where 'nested' is not actually a child of 'parent' in Passbolt; folder names misspelled or differing in case; an intermediate folder invisible to the CLI user so the chain cannot be walked; duplicate folder names at different levels causing the parent match to select the wrong instance.

Common situations: Folders renamed or re-parented in Passbolt after deploy.yml was written; permissions hiding an intermediate folder; multi-level paths with typos; same-named folders under different parents.

Related errors


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