{"record":{"id":"051be2161eb62fbf","repo":"puppetlabs/puppet","slug":"working-directory-cwd-does-not-exist","errorCode":null,"errorMessage":"Working directory %{cwd} does not exist!","messagePattern":"Working directory %(.+?) does not exist!","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/execution.rb","lineNumber":188,"sourceCode":"    end\n    if options[:gid]\n      user_log_s << \" gid=#{options[:gid]}\"\n    end\n    if user_log_s != ''\n      user_log_s.prepend(' with')\n    end\n\n    if respond_to? :debug\n      debug \"Executing#{user_log_s}: '#{command_str}'\"\n    else\n      Puppet.debug { \"Executing#{user_log_s}: '#{command_str}'\" }\n    end\n\n    null_file = Puppet::Util::Platform.windows? ? 'NUL' : '/dev/null'\n\n    cwd = options[:cwd]\n    if cwd && !Puppet::FileSystem.directory?(cwd)\n      raise ArgumentError, _(\"Working directory %{cwd} does not exist!\") % { cwd: cwd }\n    end\n\n    begin\n      stdin = Puppet::FileSystem.open(options[:stdinfile] || null_file, nil, 'r')\n      # On Windows, continue to use the file-based approach to avoid breaking people's existing\n      # manifests. If they use a script that doesn't background cleanly, such as\n      # `start /b ping 127.0.0.1`, we couldn't handle it with pipes as there's no non-blocking\n      # read available.\n      if options[:squelch]\n        stdout = Puppet::FileSystem.open(null_file, nil, 'w')\n      elsif Puppet.features.posix?\n        reader, stdout = IO.pipe\n      else\n        stdout = Puppet::FileSystem::Uniquefile.new('puppet')\n      end\n      stderr = options[:combine] ? stdout : Puppet::FileSystem.open(null_file, nil, 'w')\n\n      exec_args = [command, options, stdin, stdout, stderr]","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/execution.rb#L170-L206","documentation":"Puppet::Util.execute accepts a :cwd option to run the child process in a specific directory; before spawning it verifies the directory with Puppet::FileSystem.directory?. If :cwd is given but does not exist (or is not a directory), an ArgumentError is raised immediately and the command never runs.","triggerScenarios":"Puppet::Util.execute(['git', 'pull'], cwd: '/srv/app/current') where the directory was removed (for example a dangling symlink after a deploy) or has not been created yet at that point in the run.","commonSituations":"Exec-style code referencing release directories that get rotated or removed during deploys, cwd pointing at a mount that is not mounted yet, and typo'd absolute paths in scripts.","solutions":["Check that the directory exists before the call, and remember File.directory? follows symlinks (a dangling symlink fails)","Create the directory first (mkdir -p) or use a path guaranteed to exist such as '/'","Drop the :cwd option entirely if the child process does not actually need it"],"exampleFix":"# before\nPuppet::Util.execute(['/usr/bin/git', 'pull'], cwd: '/srv/app/checkout')\n# => ArgumentError: Working directory /srv/app/checkout does not exist!\n\n# after\nrequire 'fileutils'\nFileUtils.mkdir_p('/srv/app/checkout')\nPuppet::Util.execute(['/usr/bin/git', 'pull'], cwd: '/srv/app/checkout')","handlingStrategy":"validation","validationCode":"cwd = '/srv/app/current'\nraise ArgumentError, \"cwd #{cwd} missing\" unless cwd.nil? || File.directory?(cwd)\nPuppet::Util.execute(cmd, cwd: cwd)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate File.directory?(cwd) before passing :cwd","Order resources so directories are created before commands that cd into them","Remember File.directory? follows symlinks; check dangling links with File.realdirpath"],"tags":["execution","subprocess","cwd","filesystem","puppet"],"backgroundTag":"working-directory-not-found","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}