{"record":{"id":"44cdab1677b796ed","repo":"puppetlabs/puppet","slug":"could-not-intern-from-data-could-not-find-relatio-44cdab","errorCode":null,"errorMessage":"Could not intern from data: Could not find relationship target %{target} for %{source}","messagePattern":"Could not intern from data: Could not find relationship target %(.+?) for %(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/resource/catalog.rb","lineNumber":444,"sourceCode":"    result.add_resource(\n      *data['resources'].collect do |res|\n        Puppet::Resource.from_data_hash(res)\n      end\n    ) if data['resources']\n\n    if data['edges']\n      data['edges'].each do |edge_hash|\n        edge = Puppet::Relationship.from_data_hash(edge_hash)\n        source = result.resource(edge.source)\n        unless source\n          raise ArgumentError, _(\"Could not intern from data: Could not find relationship source %{source} for %{target}\") %\n                               { source: edge.source.inspect, target: edge.target.to_s }\n        end\n        edge.source = source\n\n        target = result.resource(edge.target)\n        unless target\n          raise ArgumentError, _(\"Could not intern from data: Could not find relationship target %{target} for %{source}\") %\n                               { target: edge.target.inspect, source: edge.source.to_s }\n        end\n        edge.target = target\n\n        result.add_edge(edge)\n      end\n    end\n\n    result.add_class(*data['classes']) if data['classes']\n\n    result.metadata = data['metadata'].transform_values { |v| Puppet::FileServing::Metadata.from_data_hash(v); } if data['metadata']\n\n    recursive_metadata = data['recursive_metadata']\n    if recursive_metadata\n      result.recursive_metadata = recursive_metadata.transform_values do |source_to_meta_hash|\n        source_to_meta_hash.transform_values do |metas|\n          metas.map { |meta| Puppet::FileServing::Metadata.from_data_hash(meta) }\n        end","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/resource/catalog.rb#L426-L462","documentation":"Companion to the source check in Puppet::Resource::Catalog.from_data_hash: after the edge source is resolved, the target is looked up via result.resource(edge.target); if absent, ArgumentError is raised with the target ref and the source name. The serialized catalog data is internally inconsistent — a relationship points at a resource that was not in data['resources'].","triggerScenarios":"A catalog data hash whose edges reference a target resource missing from the resources array (filtering removed it, or the producer never included it); mixed-version serialization where the target's ref string format changed; fixtures built by hand that declare require/notify edges without both endpoints.","commonSituations":"Editing or pruning catalog dumps and forgetting dependent edges; CI fixtures for catalog round-trips; tooling that appends custom edges (e.g. ordering hooks) referencing resources it never adds.","solutions":["Diff the refs of data['resources'] against every data['edges'][i]['target'] and add the missing resource back or drop the edge.","Regenerate the payload from a real compilation (puppet catalog compile / agent run) rather than editing it.","Pin producer and consumer to the same Puppet major/minor so ref serialization matches.","Unit-test the payload with a round-trip (to_data_hash -> from_data_hash) before shipping it."],"exampleFix":"# before\ncatalog = Puppet::Resource::Catalog.from_data_hash(data)\n\n# after — check both endpoints before interning\nrefs = data['resources'].to_a.map { |r| \"#{r['type']}[#{r['title']}]\" }.to_set\ndata['edges'].to_a.each do |e|\n  %w[source target].each do |side|\n    raise ArgumentError, \"edge #{side} #{e[side]} missing from resources\" unless refs.include?(e[side])\n  end\nend\ncatalog = Puppet::Resource::Catalog.from_data_hash(data)","handlingStrategy":"validation","validationCode":"refs = data['resources'].to_a.map { |r| \"#{r['type']}[#{r['title']}]\" }.to_set\ndata['edges'].to_a.each do |e|\n  %w[source target].each do |side|\n    raise ArgumentError, \"edge #{side} #{e[side]} missing from resources\" unless refs.include?(e[side])\n  end\nend\ncatalog = Puppet::Resource::Catalog.from_data_hash(data)","typeGuard":null,"tryCatchPattern":"begin\n  catalog = Puppet::Resource::Catalog.from_data_hash(data)\nrescue ArgumentError => e\n  raise unless e.message.start_with?('Could not intern from data')\n  # drop dangling edges and retry, or fail loudly with payload context\n  raise ArgumentError, \"inconsistent catalog payload: #{e.message}\"\nend","preventionTips":["When filtering resources from a catalog hash, always recompute the edges list in the same pass","Treat catalog payloads as immutable derived data — edit the manifests instead","Assert edge/resource consistency in fixture tests before from_data_hash"],"tags":["puppet","catalog","deserialization","relationship-edges"],"backgroundTag":"dangling-relationship-reference","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}