puppetlabs/puppet · error · ArgumentError
Cannot alias %{resource} to %{key} at %{resource_declaration
Error message
Cannot alias %{resource} to %{key} at %{resource_declaration}; resource %{newref} already declared What it means
Raised by Puppet::Resource::Catalog#alias (lib/puppet/resource/catalog.rb:215) when a computed resource reference (Type[key], built from the resource class plus the alias key or namevar) is already present in the catalog's resource table and points to a different resource object. Aliases are normally created implicitly from a resource's namevar (e.g. a file's path) or explicitly via the `alias` metaparameter, so this is Puppet's duplicate-declaration guard. The message reports the declaration site of both the offending and the pre-existing resource.
Source
Thrown at lib/puppet/resource/catalog.rb:215
# because sometimes an alias is created before the resource is
# added to the catalog, so comparing inside the below if block
# isn't sufficient.
existing = @resource_table[newref]
if existing
return if existing == resource
resource_declaration = Puppet::Util::Errors.error_location(resource.file, resource.line)
msg = if resource_declaration.empty?
# TRANSLATORS 'alias' should not be translated
_("Cannot alias %{resource} to %{key}; resource %{newref} already declared") %
{ resource: ref, key: key.inspect, newref: newref.inspect }
else
# TRANSLATORS 'alias' should not be translated
_("Cannot alias %{resource} to %{key} at %{resource_declaration}; resource %{newref} already declared") %
{ resource: ref, key: key.inspect, resource_declaration: resource_declaration, newref: newref.inspect }
end
msg += Puppet::Util::Errors.error_location_with_space(existing.file, existing.line)
raise ArgumentError, msg
end
@resource_table[newref] = resource
@aliases[ref] ||= []
@aliases[ref] << newref
end
# Apply our catalog to the local host.
# @param options [Hash{Symbol => Object}] a hash of options
# @option options [Puppet::Transaction::Report] :report
# The report object to log this transaction to. This is optional,
# and the resulting transaction will create a report if not
# supplied.
#
# @return [Puppet::Transaction] the transaction created for this
# application
#
# @api public
def apply(options = {})View on GitHub (pinned to e227c27540)
Solutions
- Read the message: it names both declarations via Puppet::Util::Errors.error_location — open each file:line and decide which declaration should win.
- If both declarations are meant to be the same resource, delete one or replace it with stdlib's ensure_resource()/ensure_packages() so the second declaration is a no-op.
- If titles must differ, give the resource its canonical namevar as title (e.g. file {'/etc/app.conf': ...}) and remove conflicting `alias` metaparameters.
- If two distinct resources are intended, change the title or namevar so they no longer produce the same Type[key] reference (different path, different defined-type title).
Example fix
# before
file { '/etc/nginx/nginx.conf':
ensure => present,
}
file { 'nginx-main-conf':
path => '/etc/nginx/nginx.conf', # namevar alias collides with File[/etc/nginx/nginx.conf]
ensure => present,
}
# after
file { '/etc/nginx/nginx.conf':
ensure => present,
}
# or make the second declaration idempotent:
# ensure_resource('file', '/etc/nginx/nginx.conf', { 'ensure' => 'present' }) Defensive patterns
Strategy: validation
Validate before calling
# before adding or aliasing a resource, confirm the reference is free
ref_string = "#{resource.type}[#{key}]"
existing = catalog.resource(ref_string)
if existing && existing != resource
raise ArgumentError, "#{ref_string} already declared at #{existing.file}:#{existing.line}"
end
catalog.alias(resource, key) Try / catch
begin
catalog.alias(resource, key)
rescue ArgumentError => e
raise unless e.message.include?('already declared')
Puppet.warning("skipping duplicate #{resource.ref}: #{e.message}")
end Prevention
- Give resources their canonical namevar as title (file path, package name) so identity is unambiguous
- Use stdlib ensure_resource/ensure_packages for resources declared from multiple modules
- Compile catalogs in CI (puppet parser validate / catalog tests) to catch duplicates before agent runs
- Avoid the `alias` metaparameter unless uniqueness of the target ref is guaranteed
When it happens
Trigger: Declaring two resources of the same type whose title or namevar resolve to the same reference, e.g. file {'/etc/app.conf': ...} plus file {'app-conf': path => '/etc/app.conf'}; using the `alias` metaparameter with a key equal to another resource's title; calling catalog.alias(resource, key) or catalog.add_resource when @resource_table[[type, key]] already holds a different resource (the method returns silently only when existing == resource or when ref_string == ref).
Common situations: Two modules in the same role/profile both manage the same file, user, or package with different titles; a refactor renames a title while another declaration still uses the old name as an alias; overlapping profiles included on one node; a resource whose namevar (path, command, name) accidentally equals another resource's title.
Related errors
- Unable to verify the SSL certificate at %{uri}
- No title provided and %{type} is not a valid resource refere
- Could not find resource '%{res}' in parameter '%{param}'
- Duplicate declaration: %{resource} is already declared; cann
- Could not deserialize catalog from %{format}: %{detail}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/ca05b260ed2a1c86.
Report an issue: GitHub.