{"record":{"id":"6ce00f2b2f9a9d08","repo":"puppetlabs/puppet","slug":"could-not-rename-corrupt-transaction-store-file","errorCode":null,"errorMessage":"Could not rename corrupt transaction store file %{filename}; remove manually","messagePattern":"Could not rename corrupt transaction store file %(.+?); remove manually","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/transaction/persistence.rb","lineNumber":94,"sourceCode":"      return\n    end\n\n    unless File.file?(filename)\n      Puppet.warning(_(\"Transaction store file %{filename} is not a file, ignoring\") % { filename: filename })\n      return\n    end\n\n    result = nil\n    Puppet::Util.benchmark(:debug, _(\"Loaded transaction store file in %{seconds} seconds\")) do\n      result = Puppet::Util::Yaml.safe_load_file(filename, self.class.allowed_classes)\n    rescue Puppet::Util::Yaml::YamlLoadError => detail\n      Puppet.log_exception(detail, _(\"Transaction store file %{filename} is corrupt (%{detail}); replacing\") % { filename: filename, detail: detail })\n\n      begin\n        File.rename(filename, filename + \".bad\")\n      rescue => detail\n        Puppet.log_exception(detail, _(\"Unable to rename corrupt transaction store file: %{detail}\") % { detail: detail })\n        raise Puppet::Error, _(\"Could not rename corrupt transaction store file %{filename}; remove manually\") % { filename: filename }, detail.backtrace\n      end\n\n      result = {}\n    end\n\n    unless result.is_a?(Hash)\n      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 }\n      return\n    end\n\n    @old_data = result\n  end\n\n  # Save data from internal class to persistence store on disk.\n  def save\n    Puppet::Util::Yaml.dump(@new_data, Puppet[:transactionstorefile])\n  end\n","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/transaction/persistence.rb#L76-L112","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Delete or move the file manually as the agent user: rm <statedir>/transactionstore.yaml (it is safely rebuilt from scratch on the next run)","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)","Clear SELinux denials (restorecon / policy) if audit logs show rename blocks","Prevent recurrence: give the state dir stable writable storage; avoid killing the agent mid-transaction"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"f = Puppet[:transactionstorefile]\nif File.exist?(f) && !File.writable?(File.dirname(f))\n  warn \"state dir not writable; transactionstore cannot be quarantined if corrupt\"\nend","typeGuard":null,"tryCatchPattern":"begin\n  persistence.load\nrescue Puppet::Error => e\n  raise unless e.message =~ /remove manually/\n  File.delete(Puppet[:transactionstorefile]) rescue nil # safe: store is rebuilt next run\n  persistence.load\nend","preventionTips":["Keep the agent state dir writable by the agent user and on stable storage","Avoid hard-killing puppet mid-run; use graceful stop","During incident recovery, know that deleting transactionstore.yaml only costs corrective-change history"],"tags":["puppet","corrupt-state","yaml","transactionstore","permissions"],"backgroundTag":"corrupt-state-file","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}