basecamp/kamal · error · ArgumentError
You must specify a destination
Error message
You must specify a destination
What it means
Kamal configurations can declare require_destination: true (read via raw_config.require_destination in Kamal::Configuration#require_destination?), which forces every invocation to pick a named destination — a config/deploy.<destination>.yml overlay on top of config/deploy.yml. During configuration load, if require_destination? is true but no destination was given (-d/--destination or KAMAL_DESTINATION), Kamal raises ArgumentError ('You must specify a destination') before any command runs.
Source
Thrown at lib/kamal/configuration.rb:327
primary_host: primary_host,
version: version,
repository: repository,
absolute_image: absolute_image,
service_with_version: service_with_version,
volume_args: volume_args,
ssh_options: ssh.to_h,
sshkit: sshkit.to_h,
builder: builder.to_h,
accessories: raw_config.accessories,
logging: logging_args
}.compact
end
private
# Will raise ArgumentError if any required config keys are missing
def ensure_destination_if_required
if require_destination? && destination.nil?
raise ArgumentError, "You must specify a destination"
end
true
end
def ensure_required_keys_present
%i[ service registry ].each do |key|
raise Kamal::ConfigurationError, "Missing required configuration for #{key}" unless raw_config[key].present?
end
raise Kamal::ConfigurationError, "Missing required configuration for image" if image.blank?
if raw_config.servers.nil?
raise Kamal::ConfigurationError, "No servers or accessories specified" unless raw_config.accessories.present?
else
unless role(primary_role_name).present?
raise Kamal::ConfigurationError, "The primary_role #{primary_role_name} isn't defined"
endView on GitHub (pinned to eee0083b38)
Solutions
- Pass the destination explicitly: `kamal deploy -d production` (or set KAMAL_DESTINATION=production for scripts).
- If the guard is unwanted, remove require_destination: true from config/deploy.yml.
- Make CI/deploy scripts destination-aware by default (export KAMAL_DESTINATION or add -d) so bare commands cannot fail or, worse, hit the wrong environment.
- Verify the overlay file exists: config/deploy.<destination>.yml for the name you pass.
Example fix
# before kamal deploy # ArgumentError: You must specify a destination # after kamal deploy -d production # or in CI: export KAMAL_DESTINATION=production kamal deploy
Defensive patterns
Strategy: validation
Validate before calling
require "yaml"
requires_dest = YAML.load_file("config/deploy.yml")["require_destination"]
abort "this config requires -d <destination>" if requires_dest && ENV["KAMAL_DESTINATION"].to_s.empty?
system("kamal deploy #{ENV["KAMAL_DESTINATION"] ? "-d #{ENV["KAMAL_DESTINATION"]}" : ""}") Type guard
def destination_satisfied?(config_hash, destination) !config_hash["require_destination"] || !destination.to_s.strip.empty? end
Try / catch
begin
Kamal::Configuration.new(create: nil, destination: ENV["DEST"])
rescue ArgumentError => e
raise unless e.message.include?("destination")
abort "set DEST (or pass -d) — this config requires an explicit destination"
end Prevention
- Export KAMAL_DESTINATION in every deploy job once you enable require_destination.
- Add -d to documented runbook commands the moment the flag becomes mandatory.
- Name destination overlay files exactly deploy.<destination>.yml to avoid follow-on errors.
When it happens
Trigger: A multi-environment setup (config/deploy.production.yml, config/deploy.staging.yml) with require_destination: true in deploy.yml, then running `kamal deploy` or `kamal setup` without -d production. The error is raised by ensure_destination_if_required during Configuration initialization, affecting every CLI command that loads config.
Common situations: Adopting the destination workflow to prevent accidental production deploys from unparameterized commands; CI pipelines not yet updated to pass -d; locally habituated `kamal deploy` after require_destination: true was added by a teammate; KAMAL_DESTINATION env var unset in the deploy job.
Related errors
- Raw is not compatible with interactive
- Detach is not compatible with #{incompatible_options.join("
- Raw is not compatible with #{incompatible_options.join(" or
- No command provided. You must specify a command to execute.
- Deploy lock held manually, not waiting. Run 'kamal lock help
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/4793e25a4424eb30.
Report an issue: GitHub.