{"record":{"id":"90d54fae33a59c43","repo":"puppetlabs/puppet","slug":"only-classes-can-set-stage-normal-resources-lik","errorCode":null,"errorMessage":"Only classes can set 'stage'; normal resources like %{resource} cannot change run stage","messagePattern":"Only classes can set 'stage'; normal resources like %(.+?) cannot change run stage","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/parser/compiler.rb","lineNumber":84,"sourceCode":"    resource = @catalog.resource(override.ref)\n    if resource\n      resource.merge(override)\n    else\n      # Otherwise, store the override for later; these\n      # get evaluated in Resource#finish.\n      @resource_overrides[override.ref] << override\n    end\n  end\n\n  def add_resource(scope, resource)\n    @resources << resource\n\n    # Note that this will fail if the resource is not unique.\n    @catalog.add_resource(resource)\n\n    if !resource.class? and resource[:stage]\n      # TRANSLATORS \"stage\" is a keyword in Puppet and should not be translated\n      raise ArgumentError, _(\"Only classes can set 'stage'; normal resources like %{resource} cannot change run stage\") % { resource: resource }\n    end\n\n    # Stages should not be inside of classes.  They are always a\n    # top-level container, regardless of where they appear in the\n    # manifest.\n    return if resource.stage?\n\n    # This adds a resource to the class it lexically appears in in the\n    # manifest.\n    unless resource.class?\n      @catalog.add_edge(scope.resource, resource)\n    end\n  end\n\n  # Store the fact that we've evaluated a class\n  def add_class(name)\n    @catalog.add_class(name) unless name == \"\"\n  end","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/parser/compiler.rb#L66-L102","documentation":"The compiler refuses the stage attribute on anything that is not a class (resource.class? is false). Run stages are a containment mechanism that only applies to classes; assigning a normal resource (file, service, or a resource from a define) to a stage raises ArgumentError.","triggerScenarios":"file { '/tmp/x': stage => pre }; any builtin/defined resource with a stage attribute; attempting to sequence plain resources via stages.","commonSituations":"Misunderstanding run stages and trying to use stage as a generic ordering metaparameter; migrating dependency chains; copy-paste from class examples onto resources.","solutions":["Remove stage from the resource","Put the resource in a class and stage the class: class { 'myapp::config': stage => pre }","Express ordering with require/before/notify/subscribe instead of stages"],"exampleFix":"// before\nfile { '/etc/app.conf': stage => pre, source => '...' }\n\n// after\nclass myapp::config { file { '/etc/app.conf': source => '...' } }\nclass { 'myapp::config': stage => pre }","handlingStrategy":"validation","validationCode":"# static pre-check over manifests: flag 'stage =>' on non-class resource declarations\ngrep -rn \"stage\\s*=>\" manifests/ | grep -v \"class {'\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the stage metaparameter only on class declarations (class { 'x': stage => pre })","Order plain resources with require/before, never with stage","Add a puppet-lint/custom check rejecting stage on non-class resources"],"tags":["puppet","dsl","run-stage","resource"],"backgroundTag":"invalid-resource-attribute","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}