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
- Add a `servers:` block with at least one role and host, e.g. `servers: { web: [ "1.2.3.4" ] }`.
- If you genuinely have no app servers, define at least one accessory so the configuration is a valid accessory-only deploy.
- 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
- Template servers via ERB only with a guard that raises when host lists are empty.
- Run `kamal config` locally before pushing config changes.
- Treat a config with neither servers nor accessories as a template, and keep it out of environments that deploy.
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
- Missing required configuration for image
- No servers specified for the #{primary_role.name} primary_ro
- No servers specified for the #{role.name} role. You can igno
- #{error_context}#{message}
- Hook `#{hook}` failed:\n#{e.message}
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/42a108378441266c.
Report an issue: GitHub.