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"
        end

View on GitHub (pinned to eee0083b38)

Solutions

  1. Pass the destination explicitly: `kamal deploy -d production` (or set KAMAL_DESTINATION=production for scripts).
  2. If the guard is unwanted, remove require_destination: true from config/deploy.yml.
  3. 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.
  4. 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

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


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