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

  1. Rewrite the mode in standard chmod syntax ('u=rw,g-w').
  2. 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

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


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/5beb00ca8cf5ce62. Report an issue: GitHub.