basecamp/kamal · error · Kamal::ConfigurationError

No servers or accessories specified

Error message

No servers or accessories specified

What it means

Raised by Kamal::Configuration#ensure_required_keys_present when the `servers:` section of config/deploy.yml is nil (key absent or explicitly null) and no `accessories:` are defined either. Kamal requires at least one deployment target — either server roles to deploy the app to, or accessories (auxiliary containers like Redis) to run. With neither, there is nothing for Kamal to do, so configuration loading aborts.

Source

Thrown at lib/kamal/configuration.rb:341

  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

        if primary_role.hosts.empty?
          raise Kamal::ConfigurationError, "No servers specified for the #{primary_role.name} primary_role"
        end

        unless allow_empty_roles?
          roles.each do |role|
            if role.hosts.empty?
              raise Kamal::ConfigurationError, "No servers specified for the #{role.name} role. You can ignore this with allow_empty_roles: true"
            end
          end
        end
      end

View on GitHub (pinned to eee0083b38)

Solutions

  1. Add a `servers:` block with at least one role and host, e.g. `servers: { web: [ "1.2.3.4" ] }`.
  2. If you genuinely have no app servers, define at least one accessory so the configuration is a valid accessory-only deploy.
  3. Fix ERB templates that can render `servers:` as null — fail loudly when host input is missing.

Example fix

# config/deploy.yml — before
service: myapp
registry: registry.example.com

# after
service: myapp
registry: registry.example.com
servers:
  web:
    - 1.2.3.4
Defensive patterns

Strategy: validation

Validate before calling

def deployable_config?(path = "config/deploy.yml")
  raw = YAML.safe_load(ERB.new(File.read(path)).result, aliases: true) || {}
  !raw["servers"].nil? || raw["accessories"].to_s.strip != ""
end

Try / catch

begin
  config = Kamal::Configuration.new(create_config_files: false)
rescue Kamal::ConfigurationError => e
  puts "Deploy config invalid: #{e.message}"
  exit 1
end

Prevention

When it happens

Trigger: `kamal deploy` or `kamal setup` with a config/deploy.yml that defines service/registry/image but omits `servers:` entirely and defines no `accessories:`; setting `servers:` to null via ERB that renders nothing; a heavily trimmed config used only for `kamal build` that still goes through full validation.

Common situations: Boilerplate configs where the servers block was deleted pending real hostnames; ERB-conditional servers blocks that render empty in CI; converting a full deploy config into a build-only config without realizing validation is global.

Related errors


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