{"record":{"id":"90ff99d0dcdd3da6","repo":"puppetlabs/puppet","slug":"found-num-dependency-cycles-n","errorCode":null,"errorMessage":"Found %{num} dependency cycles:\\n","messagePattern":"Found %(.+?) dependency cycles:\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"lib/puppet/graph/simple_graph.rb","lineNumber":247,"sourceCode":"    cycles = find_cycles_in_graph\n    number_of_cycles = cycles.length\n    return if number_of_cycles == 0\n\n    message = n_(\"Found %{num} dependency cycle:\\n\", \"Found %{num} dependency cycles:\\n\", number_of_cycles) % { num: number_of_cycles }\n\n    cycles.each do |cycle|\n      paths = paths_in_cycle(cycle)\n      message += paths.map { |path| '(' + path.join(' => ') + ')' }.join('\\n') + '\\n'\n    end\n\n    if Puppet[:graph] then\n      filename = write_cycles_to_graph(cycles)\n      message += _(\"Cycle graph written to %{filename}.\") % { filename: filename }\n    else\n      # TRANSLATORS '--graph' refers to a command line option and OmniGraffle and GraphViz are program names and should not be translated\n      message += _(\"Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz\")\n    end\n    Puppet.err(message)\n    cycles\n  end\n\n  def write_cycles_to_graph(cycles)\n    # This does not use the DOT graph library, just writes the content\n    # directly.  Given the complexity of this, there didn't seem much point\n    # using a heavy library to generate exactly the same content. --daniel 2011-01-27\n    graph = [\"digraph Resource_Cycles {\"]\n    graph << '  label = \"Resource Cycles\"'\n\n    cycles.each do |cycle|\n      paths_in_cycle(cycle, 10).each do |path|\n        graph << path.map { |v| '\"' + v.to_s.gsub(/\"/, '\\\\\"') + '\"' }.join(\" -> \")\n      end\n    end\n\n    graph << '}'\n","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/graph/simple_graph.rb#L229-L265","documentation":"Built by Puppet::Graph::SimpleGraph cycle reporting when the catalog's dependency graph contains cycles: require/before/notify/subscribe edges forming loops, often through containers or resource collections. The message lists each cycle path and points at the --graph .dot output; the run then fails because the resources cannot be ordered.","triggerScenarios":"A catalog in which resources mutually depend: A requires B while B requires A, directly or through classes, defined-type containers, stages, or relationship collectors like Resource <| |>. The graph is acyclic-checked during catalog application and report_cycle prints each loop.","commonSituations":"Profiles that both require and are required; require plus before expressed on the same pair; stage relationships mixed with class containment; an added -> chain that closes a loop; exported-resource collectors creating unexpected edges.","solutions":["Run once with `puppet agent -t --graph` and open the written .dot file in GraphViz or OmniGraffle to see the loop","Express each ordering in one direction only — use require OR before for a pair, never both","Check class containment and run stages: avoid Class['x'] requiring Class['y'] when y already contains or requires x","Simplify relationship collectors and chained arrows around the resources named in the cycle"],"exampleFix":"# before\nclass { 'apache': require => Class['app'] }\nclass { 'app':   require => Class['apache'] }\n\n# after — single direction\nclass { 'apache': }\nclass { 'app': require => Class['apache'] }","handlingStrategy":"validation","validationCode":"# spec/classes/site_spec.rb (rspec-puppet)\nrequire 'spec_helper'\n\ndescribe 'site' do\n  it 'compiles without dependency cycles' do\n    is_expected.to compile.with_all_deps   # fails the spec when the catalog has cycles\n  end\nend","typeGuard":null,"tryCatchPattern":"begin\n  catalog = compiler.compile\nrescue Puppet::Error => e\n  raise unless e.message =~ /dependency cycles/\n  run_with_graph!             # re-run `puppet agent -t --graph`, then inspect the .dot\n  raise\nend","preventionTips":["Express each relationship in exactly one direction (require OR before, not both)","Compile catalogs for key profiles in CI (rspec-puppet) so cycles fail tests, not agents","Review -> chaining, stages, and Class-level requires together — loops usually cross those boundaries"],"tags":["ruby","puppet","catalog","dependency-graph","cycle","ordering"],"backgroundTag":"circular-dependency-detected","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}