{"record":{"id":"587bc04eefb4d819","repo":"puppetlabs/puppet","slug":"could-not-destroy-name-request-detail","errorCode":null,"errorMessage":"Could not destroy %{name} %{request}: %{detail}","messagePattern":"Could not destroy %(.+?) %(.+?): %(.+?)","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/indirector/msgpack.rb","lineNumber":36,"sourceCode":"\n  def find(request)\n    load_msgpack_from_file(path(request.key), request.key)\n  end\n\n  def save(request)\n    filename = path(request.key)\n    FileUtils.mkdir_p(File.dirname(filename))\n\n    Puppet::FileSystem.replace_file(filename, 0o660) { |f| f.print to_msgpack(request.instance) }\n  rescue TypeError => detail\n    Puppet.log_exception(detail, _(\"Could not save %{name} %{request}: %{detail}\") % { name: name, request: request.key, detail: detail })\n  end\n\n  def destroy(request)\n    Puppet::FileSystem.unlink(path(request.key))\n  rescue => detail\n    unless detail.is_a? Errno::ENOENT\n      raise Puppet::Error, _(\"Could not destroy %{name} %{request}: %{detail}\") % { name: name, request: request.key, detail: detail }, detail.backtrace\n    end\n\n    1 # emulate success...\n  end\n\n  def search(request)\n    Dir.glob(path(request.key)).collect do |file|\n      load_msgpack_from_file(file, request.key)\n    end\n  end\n\n  # Return the path to a given node's file.\n  def path(name, ext = '.msgpack')\n    if name =~ Puppet::Indirector::BadNameRegexp then\n      Puppet.crit(_(\"directory traversal detected in %{indirection}: %{name}\") % { indirection: self.class, name: name.inspect })\n      raise ArgumentError, _(\"invalid key\")\n    end\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/indirector/msgpack.rb#L18-L54","documentation":"The MessagePack terminus destroy calls Puppet::FileSystem.unlink on the stored .msgpack file. Errno::ENOENT is swallowed (returns 1, emulating success), but any other error - EACCES/EPERM, EISDIR, read-only filesystem - is re-raised as Puppet::Error 'Could not destroy msgpack <key>: <original message>' with the original backtrace.","triggerScenarios":"Destroying an entry in a msgpack-backed indirection store when the datadir file is owned by another user, the filesystem is read-only, or the path is a directory.","commonSituations":"Service/datadir ownership drift after upgrades or container rebuilds; mixed root/service-user runs; read-only persistent volumes; SELinux label changes on migrated volumes.","solutions":["Read the <detail> suffix; it identifies the real errno.","chown -R <serviceuser>:<servicegroup> the datadir (Puppet[:server_datadir] / Puppet[:client_datadir]) so the service user can unlink.","Remount writable or move the datadir off the read-only filesystem.","Check SELinux audit logs and restorecon when labels are the cause."],"exampleFix":"# before\n# Could not destroy msgpack node1.example.com: Read-only file system @ unlink_internal\n\n# after: relocate the datadir to a writable volume\n# puppet.conf: [server] server_datadir = /var/lib/puppet/server_data\nsystemctl restart puppetserver","handlingStrategy":"try-catch","validationCode":"path = File.join(store_dir, indirection_name, key + '.msgpack')\nraise ArgumentError, 'not removable by this user' unless File.writable?(File.dirname(path)) && (File.writable?(path) || !File.exist?(path))","typeGuard":null,"tryCatchPattern":"begin\n  indirection.destroy(key)\nrescue Puppet::Error => e\n  Puppet.err('destroy failed: ' + e.message) # operator follow-up: fix ownership/mount\nend","preventionTips":["Keep msgpack datadir ownership under the service user.","Avoid read-only mounts for datadirs.","Include destroy operations in smoke tests."],"tags":["puppet","msgpack","filesystem","permissions","destroy"],"backgroundTag":"file-permission-denied","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}