basecamp/kamal · error · Kamal::ConfigurationError
Secret '#{key}' not found, no secret files (#{secrets_filena
Error message
Secret '#{key}' not found, no secret files (#{secrets_filenames.join(", ")}) provided What it means
Variant of the missing-secret error where zero secrets files were found on disk: neither .kamal/secrets-common nor .kamal/secrets/.kamal/secrets.<destination> exists (see secrets_filenames). The message lists the exact filenames Kamal looked for, so no secret reference in deploy.yml can ever be satisfied.
Source
Thrown at lib/kamal/secrets.rb:18
require "dotenv"
class Kamal::Secrets
Kamal::Secrets::Dotenv::InlineCommandSubstitution.install!
def initialize(destination: nil, secrets_path: ".kamal/secrets")
@destination = destination
@secrets_path = secrets_path
@mutex = Mutex.new
end
def [](key)
synchronized_fetch(key)
rescue KeyError
if secrets_files.present?
raise Kamal::ConfigurationError, "Secret '#{key}' not found in #{secrets_files.join(", ")}"
else
raise Kamal::ConfigurationError, "Secret '#{key}' not found, no secret files (#{secrets_filenames.join(", ")}) provided"
end
end
def to_h
secrets
end
def secrets_files
@secrets_files ||= secrets_filenames.select { |f| File.exist?(f) }
end
def key?(key)
synchronized_fetch(key).present?
rescue KeyError
false
end
privateView on GitHub (pinned to eee0083b38)
Solutions
- Create the secrets file(s) by fetching: kamal secrets fetch -a <adapter> --account <acct> KEY_A KEY_B >> .kamal/secrets
- If using destinations, rerun with the right destination: kamal -d staging secrets fetch ... >> .kamal/secrets.staging (or put shared keys in .kamal/secrets-common)
- Run kamal from the project root (where .kamal/ lives)
- Bootstrap CI by storing the secrets file as a secure CI variable or fetching it from a vault in a pipeline step
Example fix
# error: Secret 'PASSWORD' not found, no secret files (.kamal/secrets-common, .kamal/secrets) provided # fix (terminal) kamal secrets fetch -a one_password --account me@example.com RAILS_MASTER_KEY PASSWORD >> .kamal/secrets kamal secrets print # verify keys resolve
Defensive patterns
Strategy: validation
Validate before calling
names = [".kamal/secrets-common", ".kamal/secrets#{ENV["KAMAL_DESTINATION"] && ".#{ENV["KAMAL_DESTINATION"]}"}]
abort "no secrets files found (looked for #{names.join(", ")}) — run kamal secrets fetch first" unless names.any? { |f| File.exist?(f) } Prevention
- Bootstrap new machines/CI with a documented `kamal secrets fetch ... >> .kamal/secrets` step
- Always run kamal from the project root so relative .kamal/secrets* paths resolve
- Double-check -d <destination> — it changes which secrets file name Kamal searches for
When it happens
Trigger: deploy.yml uses <%= secrets.X %> on a fresh clone where .kamal/secrets* were never created (they are typically gitignored); running kamal from a directory other than the app root; a destination is active (KAMAL_DESTINATION or -d) so Kamal looks for .kamal/secrets.staging instead of .kamal/secrets.
Common situations: First deploy from a new machine or CI checkout; forgetting -d so the wrong destination file is searched; running kamal inside a subdirectory; onboarding a teammate without documenting the secrets bootstrap step.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Secret '#{key}' not found in #{secrets_files.join(", ")}
- You must specify a destination
- Missing required configuration for #{key}
- Missing required configuration for image
- No servers or accessories specified
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/76a1e647735b4534.
Report an issue: GitHub.