Skip to content

Commit cdeae2e

Browse files
st-imdevcursoragent
andcommitted
process: improve error message when cwd no longer exists
When the current working directory is deleted or unmounted while a Node.js process is running, process.cwd() throws an error that references the internal libuv syscall (uv_cwd) rather than process.cwd(). This makes the error confusing to debug, especially when triggered deep in dependency code. Wrap the raw cwd() call in wrappedCwd() to catch ENOENT and throw a descriptive error that: - Explicitly mentions "current working directory does not exist" - Sets syscall to "process.cwd" instead of "uv_cwd" - Preserves the ENOENT error code for programmatic checks - Re-throws non-ENOENT errors unchanged Fixes: #57045 Co-authored-by: Cursor <[email protected]>
1 parent b220fbe commit cdeae2e

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

lib/internal/bootstrap/switches/does_own_process_state.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,22 @@ function wrappedUmask(mask) {
138138
}
139139

140140
function wrappedCwd() {
141-
if (cachedCwd === '')
142-
cachedCwd = rawMethods.cwd();
141+
if (cachedCwd === '') {
142+
try {
143+
cachedCwd = rawMethods.cwd();
144+
} catch (err) {
145+
if (err.code === 'ENOENT') {
146+
const betterErr = new Error(
147+
'The current working directory does not exist. ' +
148+
'It may have been deleted or unmounted. ' +
149+
'Change to an existing directory and try again.',
150+
);
151+
betterErr.code = err.code;
152+
betterErr.syscall = 'process.cwd';
153+
throw betterErr;
154+
}
155+
throw err;
156+
}
157+
}
143158
return cachedCwd;
144159
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
'use strict';
2+
3+
// Test that process.cwd() throws a descriptive error when the current
4+
// working directory has been deleted. Regression test for
5+
// https://github.com/nodejs/node/issues/57045
6+
7+
const common = require('../common');
8+
9+
// This test is not meaningful on Windows because Windows does not allow
10+
// deleting a directory that is the cwd of a running process.
11+
if (common.isWindows) {
12+
common.skip('Windows does not allow deleting cwd of a running process');
13+
}
14+
15+
const assert = require('assert');
16+
const { execFileSync } = require('child_process');
17+
const fs = require('fs');
18+
const path = require('path');
19+
const tmpdir = require('../common/tmpdir');
20+
21+
tmpdir.refresh();
22+
23+
const dir = path.join(tmpdir.path, 'cwd-deleted');
24+
fs.mkdirSync(dir);
25+
26+
// Spawn a child process that chdir's into the temp directory, deletes it,
27+
// then attempts process.cwd(). The error should be descriptive.
28+
const child = execFileSync(process.execPath, [
29+
'-e',
30+
`process.chdir(${JSON.stringify(dir)});
31+
require('fs').rmSync(${JSON.stringify(dir)}, { recursive: true });
32+
try {
33+
process.cwd();
34+
process.exit(1); // Should not reach here
35+
} catch (err) {
36+
process.stdout.write(JSON.stringify({
37+
code: err.code,
38+
syscall: err.syscall,
39+
message: err.message,
40+
}));
41+
}`,
42+
], { encoding: 'utf8' });
43+
44+
const parsed = JSON.parse(child.trim());
45+
46+
assert.strictEqual(parsed.code, 'ENOENT');
47+
assert.strictEqual(parsed.syscall, 'process.cwd');
48+
assert.match(parsed.message, /current working directory/i);
49+
assert.match(parsed.message, /does not exist/i);

0 commit comments

Comments
 (0)