puppetlabs/puppet · error · Puppet::Error

Could not rename corrupt transaction store file %{filename};

Error message

Could not rename corrupt transaction store file %{filename}; remove manually

What it means

The transaction persistence store (Puppet[:transactionstorefile], by default state/transactionstore.yaml) records per-parameter system values between runs to power corrective_change detection. On load, if the YAML fails safe_load, Puppet logs 'is corrupt; replacing' and tries File.rename(filename, filename + '.bad'). If that rename itself fails, Puppet::Error 'Could not rename corrupt transaction store file; remove manually' propagates and the agent run aborts.

Source

Thrown at lib/puppet/transaction/persistence.rb:94

      return
    end

    unless File.file?(filename)
      Puppet.warning(_("Transaction store file %{filename} is not a file, ignoring") % { filename: filename })
      return
    end

    result = nil
    Puppet::Util.benchmark(:debug, _("Loaded transaction store file in %{seconds} seconds")) do
      result = Puppet::Util::Yaml.safe_load_file(filename, self.class.allowed_classes)
    rescue Puppet::Util::Yaml::YamlLoadError => detail
      Puppet.log_exception(detail, _("Transaction store file %{filename} is corrupt (%{detail}); replacing") % { filename: filename, detail: detail })

      begin
        File.rename(filename, filename + ".bad")
      rescue => detail
        Puppet.log_exception(detail, _("Unable to rename corrupt transaction store file: %{detail}") % { detail: detail })
        raise Puppet::Error, _("Could not rename corrupt transaction store file %{filename}; remove manually") % { filename: filename }, detail.backtrace
      end

      result = {}
    end

    unless result.is_a?(Hash)
      Puppet.err _("Transaction store file %{filename} is valid YAML but not returning a hash. Check the file for corruption, or remove it before continuing.") % { filename: filename }
      return
    end

    @old_data = result
  end

  # Save data from internal class to persistence store on disk.
  def save
    Puppet::Util::Yaml.dump(@new_data, Puppet[:transactionstorefile])
  end

View on GitHub (pinned to e227c27540)

Solutions

  1. Delete or move the file manually as the agent user: rm <statedir>/transactionstore.yaml (it is safely rebuilt from scratch on the next run)
  2. Fix permissions/ownership of the state dir so the agent can write (chown -R puppet:puppet on the cache dir, or adjust for root-run agents)
  3. Clear SELinux denials (restorecon / policy) if audit logs show rename blocks
  4. Prevent recurrence: give the state dir stable writable storage; avoid killing the agent mid-transaction
Defensive patterns

Strategy: fallback

Validate before calling

f = Puppet[:transactionstorefile]
if File.exist?(f) && !File.writable?(File.dirname(f))
  warn "state dir not writable; transactionstore cannot be quarantined if corrupt"
end

Try / catch

begin
  persistence.load
rescue Puppet::Error => e
  raise unless e.message =~ /remove manually/
  File.delete(Puppet[:transactionstorefile]) rescue nil # safe: store is rebuilt next run
  persistence.load
end

Prevention

When it happens

Trigger: Corrupt YAML (truncated by a crash/power loss mid-write, disk full, or edited by hand) combined with a rename failure: state directory not writable by the agent user, read-only filesystem, SELinux denial, or on Windows a pre-existing .bad target blocking the rename. The three-arg raise also attaches the original backtrace.

Common situations: Agent running as non-root over a state dir owned by root; puppet-agent crashes or OOM kills mid-write; NFS-mounted or read-only cache dirs; SELinux enforcing on /opt/puppetlabs/puppet/cache/state; CI containers with read-only state volumes.

Related errors


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