basecamp/kamal · error · Kamal::ConfigurationError
accessories/#{name}: unknown roles #{missing_roles.join(", "
Error message
accessories/#{name}: unknown roles #{missing_roles.join(", ")} What it means
Kamal::Configuration::Accessory#ensure_valid_roles validates an accessory's `roles:` array (the roles whose hosts the accessory should run on) against the names of roles actually defined under `servers:`. Any name not found there is collected and reported in this Kamal::ConfigurationError, prefixed with the accessory name so you know which YAML block is at fault.
Source
Thrown at lib/kamal/configuration/accessory.rb:275
end
def extract_hosts_from_config_with_tag(tag)
if (servers_with_roles = config.raw_config.servers).is_a?(Hash)
servers_with_roles.flat_map do |role, servers_in_role|
servers_in_role.filter_map do |host|
host.keys.first if host.is_a?(Hash) && host.values.first.include?(tag)
end
end
end
end
def network
accessory_config["network"] || DEFAULT_NETWORK
end
def ensure_valid_roles
if accessory_config["roles"] && (missing_roles = accessory_config["roles"] - config.roles.map(&:name)).any?
raise Kamal::ConfigurationError, "accessories/#{name}: unknown roles #{missing_roles.join(", ")}"
elsif accessory_config["role"] && !config.role(accessory_config["role"])
raise Kamal::ConfigurationError, "accessories/#{name}: unknown role #{accessory_config["role"]}"
end
end
end
View on GitHub (pinned to eee0083b38)
Solutions
- Align the accessory's `roles:` entries with the exact keys under `servers:` (check spelling and singular/plural).
- If the role was renamed, update the accessory to the new name.
- Run `kamal config` to list the actual role names before fixing the accessory.
Example fix
# config/deploy.yml — before
servers:
web:
- 1.2.3.4
workers:
- 1.2.3.5
accessories:
redis:
roles: [ "sidekiq" ]
# after
servers:
web:
- 1.2.3.4
workers:
- 1.2.3.5
accessories:
redis:
roles: [ "workers" ] Defensive patterns
Strategy: validation
Validate before calling
def accessory_roles_valid?(raw)
role_names = raw["servers"].is_a?(Array) ? ["web"] : raw["servers"].keys.map(&:to_s)
raw["accessories"].to_h.all? do |_name, cfg|
Array(cfg["roles"]).all? { |r| role_names.include?(r.to_s) }
end
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
- After renaming a servers role, grep accessories for the old name.
- List real roles with `kamal config` before writing accessory role references.
- Prefer `roles:` (array) for clarity over singular `role:` in new configs.
When it happens
Trigger: An accessory in config/deploy.yml declaring `roles: [ "sidekiq" ]` when servers define `workers:` instead; renaming a role without updating accessories referencing it; a plural `roles:` array containing one valid and one misspelled role name — the missing ones are listed in the message.
Common situations: Role renames during refactors that miss accessory references; copy-pasted accessory configs from another project with different role names; singular/plural confusion between `role` and `roles` keys.
Related errors
- Conflicting proxy run configurations for host #{host}
- accessories/#{name}: unknown role #{accessory_config["role"]
- The primary_role #{primary_role_name} isn't defined
- No servers specified for the #{primary_role.name} primary_ro
- No servers specified for the #{role.name} role. You can igno
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/74cd311f41499f49.
Report an issue: GitHub.