{"record":{"id":"cef720bf1bb3e487","repo":"puppetlabs/puppet","slug":"could-not-remove-existing-file","errorCode":null,"errorMessage":"Could not remove existing file","messagePattern":"Could not remove existing file","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/type/file/target.rb","lineNumber":45,"sourceCode":"    newvalue(/./) do\n      @resource[:ensure] = :link unless @resource.should(:ensure)\n\n      # Only call mklink if ensure didn't call us in the first place.\n      currentensure = @resource.property(:ensure).retrieve\n      mklink if @resource.property(:ensure).safe_insync?(currentensure)\n    end\n\n    # Create our link.\n    def mklink\n      raise Puppet::Error, \"Cannot symlink on this platform version\" unless provider.feature?(:manages_symlinks)\n\n      target = should\n\n      # Clean up any existing objects.  The argument is just for logging,\n      # it doesn't determine what's removed.\n      @resource.remove_existing(target)\n\n      raise Puppet::Error, \"Could not remove existing file\" if Puppet::FileSystem.exist?(@resource[:path])\n\n      Puppet::Util::SUIDManager.asuser(@resource.asuser) do\n        mode = @resource.should(:mode)\n        if mode\n          Puppet::Util.withumask(0o00) do\n            Puppet::FileSystem.symlink(target, @resource[:path])\n          end\n        else\n          Puppet::FileSystem.symlink(target, @resource[:path])\n        end\n      end\n\n      @resource.send(:property_fix)\n\n      :link_created\n    end\n\n    def insync?(currentvalue)","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/type/file/target.rb#L27-L63","documentation":"Inside mklink, Puppet first calls remove_existing(target) to clear whatever occupies the link path, then verifies with Puppet::FileSystem.exist? that the path is actually gone. If the entry survived removal (permissions, read-only attributes, open handles, non-empty directory), it raises 'Could not remove existing file' rather than letting symlink(2) fail obscurely.","triggerScenarios":"`ensure => link` onto a path occupied by a file the agent cannot delete (EACCES/EPERM); a Windows file with the read-only attribute or an open handle; the existing entry being a non-empty directory; another process re-creating the path between removal and the check.","commonSituations":"Windows agents hitting locked/read-only files (AV scanners, backup agents); agent running non-root over root-owned entries; deployment layouts where 'current' exists as a directory from a previous release.","solutions":["Inspect the path: ls -ld (POSIX) or handle.exe (Windows) and clear the entry manually.","Manage the conflicting object in Puppet: a file resource with ensure => absent ordered before the link.","On Windows, remove read-only attributes, close locking processes, and run elevated.","If the entry is a directory, remove it (or manage its removal) before creating the link."],"exampleFix":"// before: /opt/app/current occupied by a locked file\nfile { '/opt/app/current':\n  ensure => link,\n  target => '/opt/app/releases/2026.08',\n}\n\n// after: manage removal first, then the link\nfile { '/opt/app/current': ensure => absent }\n->\nfile { '/opt/app/current':\n  ensure => link,\n  target => '/opt/app/releases/2026.08',\n}","handlingStrategy":"validation","validationCode":"# Ruby pre-flight before creating a link\nif Puppet::FileSystem.exist?(link_path)\n  st = File.lstat(link_path)\n  fail(\"cannot clear #{link_path} (#{st.ftype}) — remove it or manage ensure => absent first\") unless File.writable?(File.dirname(link_path))\nend","typeGuard":null,"tryCatchPattern":"rescue Puppet::Error on /Could not remove existing file/; lstat the path, close locks / clear read-only attributes / pre-remove the entry, then re-run the agent — creation is idempotent.","preventionTips":["Manage the old object explicitly (ensure => absent) before introducing the link.","Check open handles on Windows (handle.exe, Resource Monitor).","Ensure the agent user can write the containing directory.","Keep AV/backup agents from recreating the path mid-run."],"tags":["puppet","file","symlink","file-removal","permissions"],"backgroundTag":"file-replace-failure","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}