{"record":{"id":"c6ca6812386b5aaf","repo":"puppetlabs/puppet","slug":"could-not-find-node-statement-with-name-default","errorCode":null,"errorMessage":"Could not find node statement with name 'default' or '%{names}'","messagePattern":"Could not find node statement with name 'default' or '%(.+?)'","errorType":"exception","errorClass":"Puppet::ParseError","httpStatus":null,"severity":"error","filePath":"lib/puppet/parser/compiler.rb","lineNumber":220,"sourceCode":"    evaluate_classes(classes_without_params, @node_scope || topscope)\n  end\n\n  # If ast nodes are enabled, then see if we can find and evaluate one.\n  #\n  # @api private\n  def evaluate_ast_node\n    krt = environment.known_resource_types\n    return unless krt.nodes? # ast_nodes?\n\n    # Now see if we can find the node.\n    astnode = nil\n    @node.names.each do |name|\n      astnode = krt.node(name.to_s.downcase)\n      break if astnode\n    end\n\n    unless astnode ||= krt.node(\"default\")\n      raise Puppet::ParseError, _(\"Could not find node statement with name 'default' or '%{names}'\") % { names: node.names.join(\", \") }\n    end\n\n    # Create a resource to model this node, and then add it to the list\n    # of resources.\n    resource = astnode.ensure_in_catalog(topscope)\n\n    resource.evaluate\n\n    @node_scope = topscope.class_scope(astnode)\n  end\n\n  # Evaluates each specified class in turn. If there are any classes that\n  # can't be found, an error is raised. This method really just creates resource objects\n  # that point back to the classes, and then the resources are themselves\n  # evaluated later in the process.\n  #\n  def evaluate_classes(classes, scope, lazy_evaluate = true)\n    raise Puppet::DevError, _(\"No source for scope passed to evaluate_classes\") unless scope.source","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/parser/compiler.rb#L202-L238","documentation":"When the environment's code contains node statements (known_resource_types.nodes? is true), evaluate_ast_node looks for a node definition matching any of the node's names (certname, fqdn...) and falls back to node default. If neither exists it raises Puppet::ParseError listing the names tried. Note: once any node statement exists, every node must match one of them or node default.","triggerScenarios":"site.pp contains node 'web1.example.com' { ... } but the compiling node is web2.example.com and there is no node default block; certname or fqdn changed after certificate regeneration; misspelled node names.","commonSituations":"Classic classification mistake: adding the first node statement silently removes the implicit 'compile main for everyone' behavior; hostname/certname drift; environment whose site.pp was edited for one node only.","solutions":["Add a catch-all: node default { include baseline }","Correct the node statement to match the certname (or set the agent's certname explicitly)","Or remove node statements entirely and classify via ENC/group profiles"],"exampleFix":"// before\nsite.pp: node 'web1.example.com' { include role::web }\n\n// after\nsite.pp:\nnode 'web1.example.com' { include role::web }\nnode default { include role::baseline }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  compiler.compile\nrescue Puppet::ParseError => e\n  if e.message.include?('Could not find node statement')\n    # classification gap: log node names and fall back to a baseline catalog\n  end\n  raise\nend","preventionTips":["Always define node default when using node statements in site.pp","Pin agent certname explicitly so node matching is deterministic","Prefer ENC or role/profile classification over node statements"],"tags":["puppet","site-pp","node-classification","dsl"],"backgroundTag":"no-matching-node-definition","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}