puppetlabs/puppet · error · Puppet::Error
Missing operation (-, =, or +)
Error message
Missing operation (-, =, or +)
What it means
Raised when the inner symbolic-mode loop tries to apply a permission while no -, +, or = operator has been seen yet — the internal action variable is still its '!' sentinel, whose lambda raises. Because the upstream clause regex requires an operator right after the who list, public inputs normally fail earlier with 'Missing action'; hitting this message usually means a malformed fragment reached the parser through a nonstandard path.
Source
Thrown at lib/puppet/util/symbolic_file_mode.rb:95
modification.split(/\s*,\s*/).each do |part|
_, to, dsl = /^([ugoa]*)([-+=].*)$/.match(part).to_a
if dsl.nil? then raise Puppet::Error, _('Missing action') end
to = "a" unless to and to.length > 0
# We want a snapshot of the mode before we start messing with it to
# make actions like 'a-g' atomic. Various parts of the DSL refer to
# the original mode, the final mode, or the current snapshot of the
# mode, for added fun.
snapshot_mode = {}
final_mode.each { |k, v| snapshot_mode[k] = v }
to.gsub('a', 'ugo').split('').uniq.each do |who|
value = snapshot_mode[who]
action = '!'
actions = {
'!' => ->(_, _) { raise Puppet::Error, _('Missing operation (-, =, or +)') },
'=' => ->(m, v) { m | v },
'+' => ->(m, v) { m | v },
'-' => ->(m, v) { m & ~v },
}
dsl.split('').each do |op|
case op
when /[-+=]/
action = op
# Clear all bits, if this is assignment
value = 0 if op == '='
when /[ugo]/
value = actions[action].call(value, snapshot_mode[op])
when /[rwx]/
value = actions[action].call(value, SymbolicMode[op])
View on GitHub (pinned to e227c27540)
Solutions
- Rewrite the mode in standard chmod syntax ('u=rw,g-w').
- If hit from manifest input, simplify the mode string and retry; if it reproduces on current Puppet, file a bug with the exact mode value.
Example fix
# before
Puppet::Util::SymbolicMode.symbolic_mode_to_int('u=rw,g-w-ish')
# after
Puppet::Util::SymbolicMode.symbolic_mode_to_int('u=rw,g-w') Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, 'invalid mode' unless mode =~ /^([ugoa]*)([-+=][ugo rwxXst]*)+(,[ugoa]*[-+=][ugo rwxXst]*)*$/ Puppet::Util::SymbolicMode.symbolic_mode_to_int(mode)
Try / catch
begin
int_mode = Puppet::Util::SymbolicMode.symbolic_mode_to_int(mode, File.stat(path).mode)
rescue Puppet::Error => e
raise "bad symbolic mode #{mode.inspect} for #{path}: #{e.message}"
end Prevention
- Use canonical chmod syntax only.
- Test generated mode strings against the parser in rspec.
- Treat a hit as a parser bug candidate and minimize the input.
When it happens
Trigger: A dsl fragment referencing permissions or who-letters before any operator character; in practice only reachable by calling symbolic_mode_to_int with hand-split or programmatically assembled clause fragments, since manifest input lacking an operator is caught by the 'Missing action' check first.
Common situations: Almost never seen from manifests; appears when wrapper code pre-splits or reassembles mode strings before calling the parser.
Related errors
- Missing action
- Unknown operation
- X only works with the '+' operator
- %{error}%{rest} in symbolic mode %{modification}
- One or more file(s) specified did not exist: %{files}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/5beb00ca8cf5ce62.
Report an issue: GitHub.