{"record":{"id":"b71a9bf935a39027","repo":"basecamp/kamal","slug":"no-secrets-given-to-fetch","errorCode":null,"errorMessage":"No secrets given to fetch","messagePattern":"No secrets given to fetch","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/kamal/secrets/adapters/passbolt.rb","lineNumber":15,"sourceCode":"class Kamal::Secrets::Adapters::Passbolt < Kamal::Secrets::Adapters::Base\n  def requires_account?\n    false\n  end\n\n  private\n\n    def login(*)\n      `passbolt verify`\n      raise RuntimeError, \"Failed to login to Passbolt\" unless $?.success?\n    end\n\n    def fetch_secrets(secrets, from:, **)\n      secrets = prefixed_secrets(secrets, from: from)\n      raise ArgumentError, \"No secrets given to fetch\" if secrets.empty?\n\n      secret_names = secrets.collect { |s| s.split(\"/\").last }\n      folders = secrets_get_folders(secrets)\n\n      # build filter conditions for each secret with its corresponding folder\n      filter_conditions = []\n      secrets.each do |secret|\n        parts = secret.split(\"/\")\n        secret_name = parts.last\n\n        if parts.size > 1\n          # get the folder path without the secret name\n          folder_path = parts[0..-2]\n\n          # find the most nested folder for this path\n          current_folder = nil\n          current_path = []\n","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/basecamp/kamal/blob/eee0083b38661c3707c6b6052cc89e85038a096c/lib/kamal/secrets/adapters/passbolt.rb#L1-L33","documentation":"Raised in Passbolt#fetch_secrets as an ArgumentError (not RuntimeError, unlike sibling adapter errors) when the secrets array is empty after prefixed_secrets mapping. It is an input-validation guard: the passbolt adapter refuses to build its folder/name filter query for a zero-length request. Since Base#fetch always reaches fetch_secrets after dependency/login checks, this fires only when the caller passed no secret names at all.","triggerScenarios":"adapter.fetch([], from: ...) — e.g. `kamal secrets pull` invoked with no secrets configured/selected for the passbolt adapter (empty secrets list in deploy config, or an empty SECRETS env/argument evaluated before the call).","commonSituations":"Skeleton deploy.yml where the secrets: section is still empty but a secrets pull was triggered; scripts that compute the secret list dynamically and pass an empty array on first run; copy-paste from another adapter that tolerates empty lists.","solutions":["Define the secrets you need in your kamal configuration (secrets: [ \"ITEM\", ... ]) so the pull has at least one name.","If your wrapper computes names dynamically, skip the fetch entirely when the list is empty instead of calling the adapter.","Pass names explicitly: `kamal secrets pull RAILS_MASTER_KEY` (adapter-specific CLI usage) when no config list exists yet."],"exampleFix":"# before\nadapter.fetch([], from: \"Team\")   # -> ArgumentError: No secrets given to fetch\n\n# after\nadapter.fetch([\"RAILS_MASTER_KEY\"], from: \"Team\")\n# or guard at the call site:\n#   adapter.fetch(names, from: \"Team\") unless names.empty?","handlingStrategy":"validation","validationCode":"def fetch_passbolt_secrets!(adapter, names, from:)\n  raise ArgumentError, \"No secrets requested — nothing to pull from Passbolt\" if names.to_a.empty?\n  adapter.fetch(names, from: from)\nend","typeGuard":"def valid_secret_list?(names)\n  names.is_a?(Array) && !names.empty? && names.all? { |n| n.is_a?(String) && !n.strip.empty? }\nend","tryCatchPattern":"begin\n  adapter.fetch(names, from: \"Team\")\nrescue ArgumentError => e\n  raise \"Passbolt adapter needs at least one secret name; populate your secrets list\" if e.message == \"No secrets given to fetch\"\n  raise\nend","preventionTips":["Guard at the call site: skip the fetch (or fail with your own message) when the computed secret list is empty.","Populate the secrets section of your kamal config before wiring the passbolt adapter into pull scripts.","Note this adapter raises ArgumentError (not RuntimeError) — rescue accordingly if you branch on exception class."],"tags":["ruby","kamal","passbolt","secrets","argument-validation","empty-list"],"backgroundTag":"missing-required-argument","analyzedSha":"eee0083b38661c3707c6b6052cc89e85038a096c","analyzedAt":"2026-08-21T15:17:22.045Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}