{"record":{"id":"47ab1d64be7d7dfe","repo":"basecamp/kamal","slug":"could-not-find-the-following-folders-in-passbolt","errorCode":null,"errorMessage":"Could not find the following folders in Passbolt: #{missing_paths.join(\", \")}","messagePattern":"Could not find the following folders in Passbolt: #(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/kamal/secrets/adapters/passbolt.rb","lineNumber":106,"sourceCode":"        # for each nested level, get the folders using the parent's ID\n        current_parent = parent_folder\n        path[1..-1].each do |folder_name|\n          filter_condition = \"--filter 'Name == #{folder_name.shellescape.inspect} && FolderParentID == #{current_parent[\"id\"].shellescape.inspect}'\"\n          fetch_nested = `passbolt list folders #{filter_condition} --json`\n          next unless $?.success?\n\n          nested_folders = JSON.parse(fetch_nested)\n          break if nested_folders.empty?\n\n          all_folders.concat(nested_folders)\n          current_parent = nested_folders.first\n        end\n      end\n\n      # check if we found all required folders\n      found_paths = all_folders.map { |f| get_folder_path(f, all_folders) }\n      missing_paths = folder_paths.map { |path| path.join(\"/\") } - found_paths\n      raise RuntimeError, \"Could not find the following folders in Passbolt: #{missing_paths.join(\", \")}\" if missing_paths.any?\n\n      all_folders\n    end\n\n    def get_folder_path(folder, all_folders, path = [])\n      path.unshift(folder[\"name\"])\n      return path.join(\"/\") if folder[\"folder_parent_id\"].to_s.empty?\n\n      parent = all_folders.find { |f| f[\"id\"] == folder[\"folder_parent_id\"] }\n      return path.join(\"/\") unless parent\n\n      get_folder_path(parent, all_folders, path)\n    end\n\n    def check_dependencies!\n      raise RuntimeError, \"Passbolt CLI is not installed\" unless cli_installed?\n    end\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/basecamp/kamal/blob/eee0083b38661c3707c6b6052cc89e85038a096c/lib/kamal/secrets/adapters/passbolt.rb#L88-L124","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run `passbolt list folders --json` and confirm the exact parent-to-child chain; names are case-sensitive.","Fix the path segments in deploy.yml's passbolt references so they mirror the real hierarchy.","Grant the CLI user read access to every folder along the path, not just the leaf.","Rename duplicate or oddly named folders to unique, simple names so resolution is unambiguous."],"exampleFix":"// before\nsecrets:\n  - TOKEN=passbolt/infra/prod/api_token   # 'prod' is not under 'infra'\n\n// after\nsecrets:\n  - TOKEN=passbolt/prod/api_token          # matches the actual folder chain","handlingStrategy":"validation","validationCode":"# Rough preflight: every folder segment referenced must exist\nsegments = %w[infra prod]\nnames = JSON.parse(`passbolt list folders --json`).map { |f| f[\"name\"] }\nmissing = segments.uniq - names\nabort \"Missing folders in Passbolt: #{missing.join(', ')}\" if missing.any?","typeGuard":null,"tryCatchPattern":null,"preventionTips":["After renaming or re-parenting folders in Passbolt, grep deploy.yml for stale paths","Grant the CLI user read on the whole folder chain, not just the leaf","Avoid duplicate folder names across levels so parent matching is unambiguous"],"tags":["passbolt","kamal","folders","not-found","path-mismatch"],"backgroundTag":"path-not-found","analyzedSha":"eee0083b38661c3707c6b6052cc89e85038a096c","analyzedAt":"2026-08-21T15:17:22.045Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}