puppetlabs/puppet · critical
Found %{num} dependency cycles:\n
Error message
Found %{num} dependency cycles:\n What it means
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.
Source
Thrown at lib/puppet/graph/simple_graph.rb:247
cycles = find_cycles_in_graph
number_of_cycles = cycles.length
return if number_of_cycles == 0
message = n_("Found %{num} dependency cycle:\n", "Found %{num} dependency cycles:\n", number_of_cycles) % { num: number_of_cycles }
cycles.each do |cycle|
paths = paths_in_cycle(cycle)
message += paths.map { |path| '(' + path.join(' => ') + ')' }.join('\n') + '\n'
end
if Puppet[:graph] then
filename = write_cycles_to_graph(cycles)
message += _("Cycle graph written to %{filename}.") % { filename: filename }
else
# TRANSLATORS '--graph' refers to a command line option and OmniGraffle and GraphViz are program names and should not be translated
message += _("Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz")
end
Puppet.err(message)
cycles
end
def write_cycles_to_graph(cycles)
# This does not use the DOT graph library, just writes the content
# directly. Given the complexity of this, there didn't seem much point
# using a heavy library to generate exactly the same content. --daniel 2011-01-27
graph = ["digraph Resource_Cycles {"]
graph << ' label = "Resource Cycles"'
cycles.each do |cycle|
paths_in_cycle(cycle, 10).each do |path|
graph << path.map { |v| '"' + v.to_s.gsub(/"/, '\\"') + '"' }.join(" -> ")
end
end
graph << '}'
View on GitHub (pinned to e227c27540)
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
Example fix
# before
class { 'apache': require => Class['app'] }
class { 'app': require => Class['apache'] }
# after — single direction
class { 'apache': }
class { 'app': require => Class['apache'] } Defensive patterns
Strategy: validation
Validate before calling
# spec/classes/site_spec.rb (rspec-puppet)
require 'spec_helper'
describe 'site' do
it 'compiles without dependency cycles' do
is_expected.to compile.with_all_deps # fails the spec when the catalog has cycles
end
end Try / catch
begin catalog = compiler.compile rescue Puppet::Error => e raise unless e.message =~ /dependency cycles/ run_with_graph! # re-run `puppet agent -t --graph`, then inspect the .dot raise end
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- %{message} on node %{node}
- 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
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/90ff99d0dcdd3da6.
Report an issue: GitHub.