basecamp/kamal · error · ArgumentError
No --roles match for #{role_names.join(',')}
Error message
No --roles match for #{role_names.join(',')} What it means
Kamal::Commander#specific_roles= is called when you pass the global --roles filter (e.g. `kamal deploy --roles web,workers` or programmatic use). It filters config.roles through Kamal::Utils.filter_specific_items, which uses File.fnmatch with FNM_EXTGLOB — so filters support fnmatch patterns like 'web*' or extended globs, matched against role names. If no configured role matches any filter, the filtered list is empty and Kamal raises ArgumentError ('No --roles match for ...').
Source
Thrown at lib/kamal/commander.rb:59
def configured?
@config || @config_kwargs
end
def specific_primary!
@specifics = nil
if specific_roles.present?
self.specific_hosts = [ specific_roles.first.primary_host ]
else
self.specific_hosts = [ config.primary_host ]
end
end
def specific_roles=(role_names)
@specifics = nil
@specific_roles = if role_names.present?
filtered = Kamal::Utils.filter_specific_items(role_names, config.roles)
raise ArgumentError, "No --roles match for #{role_names.join(',')}" if filtered.empty?
filtered
end
end
def specific_hosts=(hosts)
@specifics = nil
@specific_hosts = if hosts.present?
filtered = Kamal::Utils.filter_specific_items(hosts, config.all_hosts)
raise ArgumentError, "No --hosts match for #{hosts.join(',')}" if filtered.empty?
filtered
end
end
def with_specific_hosts(hosts)
original_hosts, self.specific_hosts = specific_hosts, hosts
yield
ensure
self.specific_hosts = original_hostsView on GitHub (pinned to eee0083b38)
Solutions
- List the roles actually defined in your config (grep `servers:` block names in config/deploy*.yml or run `kamal app details`) and correct the --roles value to match.
- If you meant a pattern, ensure it is fnmatch-compatible ('web*' works; regex like 'web|workers' does not).
- Update CI/alias scripts after renaming roles in deploy.yml.
- If targeting a specific host instead, use --hosts with a hostname from config.
Example fix
# before # config/deploy.yml defines servers: web: ..., workers: ... kamal deploy --roles webb # typo -> No --roles match for webb # after kamal deploy --roles web # patterns are fnmatch-style: kamal deploy --roles 'w*'
Defensive patterns
Strategy: validation
Validate before calling
require "yaml"
configured = YAML.load_file("config/deploy.yml")["servers"].keys # role names
requested = %w[web workers]
unknown = requested.reject { |r| configured.include?(r) || configured.any? { |c| File.fnmatch(r, c) } }
abort "no roles match #{unknown.join(',')}" unless unknown.empty?
system("kamal deploy --roles #{requested.join(',')}") Type guard
def roles_match?(filters, configured_roles)
filters.any? { |f| configured_roles.any? { |r| File.fnmatch(f, r, File::FNM_EXTGLOB) } }
end Try / catch
begin
Kamal::Commander.new.specific_roles = %w[web]
rescue ArgumentError => e
raise unless e.message.include?("--roles")
abort "check role names in config/deploy.yml: #{e.message}"
end Prevention
- Centralize role names as a shared constant between deploy.yml and CI scripts.
- Remember filters are fnmatch globs ('web*'), not regexes.
- After renaming roles, grep CI configs and runbooks for old --roles values.
When it happens
Trigger: `kamal app boot --roles web2` when config defines only web/workers; using a glob that matches nothing (`--roles job*` with no job roles); quoting issues so the filter string includes stray characters; renaming roles in deploy.yml but running old scripts with the previous names.
Common situations: Role renamed during config refactor while CI pipelines still pass the old --roles value; typos in role names; destination configs (deploy.staging.yml) defining a different role subset than production; glob syntax expectations differing from fnmatch semantics.
Related errors
- No --hosts match for #{hosts.join(',')}
- Raw is not compatible with interactive
- Detach is not compatible with #{incompatible_options.join("
- Raw is not compatible with #{incompatible_options.join(" or
- No command provided. You must specify a command to execute.
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/038926b0d6697a68.
Report an issue: GitHub.