Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

process: improve error message for process.cwd() when directory is deleted #57053

Closed
wants to merge 9 commits into from
8 changes: 8 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,14 @@ added:

An attempt to invoke an unsupported crypto operation was made.

<a id="ERR_CWD_DELETED"></a>

### `ERR_CWD_DELETED`

The current working directory has been deleted while the process was still inside it.

To resolve this, use `process.chdir()` to switch to a valid directory.

<a id="ERR_DEBUGGER_ERROR"></a>

### `ERR_DEBUGGER_ERROR`
Expand Down
3 changes: 2 additions & 1 deletion lib/internal/bootstrap/switches/does_own_process_state.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ function wrappedUmask(mask) {
}

function wrappedCwd() {
if (cachedCwd === '')
if (cachedCwd === '') {
cachedCwd = rawMethods.cwd();
}
return cachedCwd;
}
5 changes: 5 additions & 0 deletions src/node_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void OOMErrorHandler(const char* location, const v8::OOMDetails& details);

#define ERRORS_WITH_CODE(V) \
V(ERR_ACCESS_DENIED, Error) \
V(ERR_CWD_DELETED, Error) \
V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, Error) \
V(ERR_BUFFER_OUT_OF_BOUNDS, RangeError) \
V(ERR_BUFFER_TOO_LARGE, Error) \
Expand Down Expand Up @@ -172,6 +173,10 @@ ERRORS_WITH_CODE(V)
V(ERR_ACCESS_DENIED, "Access to this API has been restricted") \
V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, \
"Buffer is not available for the current Context") \
V(ERR_CWD_DELETED, \
"Current working directory does not exist. " \
"It may have been deleted while the process was still " \
"inside it. Use process.chdir() to change to a valid directory.") \
V(ERR_CLOSED_MESSAGE_PORT, "Cannot send data on closed MessagePort") \
V(ERR_CONSTRUCT_CALL_INVALID, "Constructor cannot be called") \
V(ERR_CONSTRUCT_CALL_REQUIRED, "Cannot call constructor without `new`") \
Expand Down
4 changes: 4 additions & 0 deletions src/node_process_methods.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ static void Cwd(const FunctionCallbackInfo<Value>& args) {
char buf[PATH_MAX_BYTES];
size_t cwd_len = sizeof(buf);
int err = uv_cwd(buf, &cwd_len);
if (err == UV_ENOENT) {
THROW_ERR_CWD_DELETED(env);
return;
}
if (err) {
return env->ThrowUVException(err, "uv_cwd");
}
Expand Down
36 changes: 36 additions & 0 deletions test/parallel/test-process-cwd-deleted.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

// This test verifies that an appropriate error is thrown when the current
// working directory is deleted and process.cwd() is called.
//
// We do this by spawning a forked process and deleting the tmp cwd
// while it is starting up.

const common = require('../common');

const { fork } = require('node:child_process');
const { rmSync } = require('node:fs');
const { strictEqual, ok } = require('node:assert');
const { Buffer } = require('node:buffer');

if (process.argv[2] === 'child') {
return;
}

const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
const tmpDir = tmpdir.path;

const proc = fork(__filename, ['child'], {
cwd: tmpDir,
silent: true,
});
proc.on('spawn', common.mustCall(() => rmSync(tmpDir, { recursive: true })));

proc.on('exit', common.mustCall((code) => {
strictEqual(code, 1);
proc.stderr.toArray().then(common.mustCall((chunks) => {
const buf = Buffer.concat(chunks);
ok(/Current working directory does not exist/.test(buf.toString()));
}));
}));