basecamp/kamal · error · Kamal::ConfigurationError
No servers specified for the #
Error message
No servers specified for the #{primary_role.name} primary_role What it means
Kamal::Configuration#ensure_required_keys_present checks that the primary role — which does exist as a key under `servers:` — has a non-empty hosts list. A role entry with empty hosts (e.g. `web: { hosts: [] }` or an ERB-rendered empty array) means Kamal has no machine to run migrations, health checks, or traffic switching on, so validation aborts with the role name interpolated into the message.
Solutions
- Give the primary role at least one host: `web: { hosts: [ "1.2.3.4" ] }`.
- If hosts come from ERB/ENV, make missing values fail loudly (raise in the template) instead of rendering an empty array.
- Verify with `kamal config` (or `kamal config roles`) that the rendered hosts list is what you expect before deploying.
Example fix
# config/deploy.yml — before
servers:
web:
hosts: <%= ENV["WEB_HOSTS"]&.split(",") %>
# after
servers:
web:
hosts: <%= (ENV["WEB_HOSTS"] or raise "WEB_HOSTS not set").split(",") %> Defensive patterns
Strategy: validation
Validate before calling
def primary_role_has_hosts?(path = "config/deploy.yml")
raw = YAML.safe_load(ERB.new(File.read(path)).result, aliases: true) || {}
primary = raw["primary_role"] || "web"
entry = raw["servers"][primary] rescue nil
hosts = entry.is_a?(Hash) ? entry["hosts"] : entry
Array(hosts).any? { |h| (h.is_a?(Hash) ? h.keys.first : h).to_s != "" }
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
- Render host lists from ENV with explicit failure: `<%= ENV.fetch("WEB_HOSTS") %>`.
- Run `kamal config` after any change to ERB host templating.
- Keep at least one staging/production host committed per environment overlay.
When it happens
Trigger: `servers: { web: { hosts: [] } }` after ERB renders an empty list because the source env var or loop produced nothing; a hosts list built from `<%= ENV["WEB_HOSTS"]&.split(",") %>` that yields an empty array; a YAML role key with no hosts value at all.
Common situations: Templated multi-environment configs where one environment has no web hosts yet; stashing hosts in ENV and forgetting to export it in the deploy shell; refactoring hosts from an inline array to ERB and silently breaking it.
Related errors
- No servers specified for the #
- accessories/# : unknown role #
- accessories/# : unknown roles #
- Conflicting proxy run configurations for host #
- Different roles can't share the same host for SSL: #
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/d7c63419053af48d.
Report an issue: GitHub.
Appendix: source
Thrown at lib/kamal/configuration.rb:348
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
true
end
def ensure_valid_service_name
raise Kamal::ConfigurationError, "Service name can only include alphanumeric characters, hyphens, and underscores" unless raw_config[:service] =~ /^[a-z0-9_-]+$/i
trueView on GitHub (pinned to eee0083b38)