TypeError [ERR_INVALID_ARG_TYPE] means a Node.js built-in received the wrong JavaScript type — almost always undefined or a Promise where a string was expected. Read the argument name in the error message ("path", "data", "chunk", "from"), add a console.log right before the failing call to see the actual value, then trace it back to a missing env var, a missing await, an undefined __dirname in ESM, or an unserialised object.
What is ERR_INVALID_ARG_TYPE?
ERR_INVALID_ARG_TYPE is a TypeError thrown by Node.js core APIs
when a function argument fails the internal type check. Unlike JavaScript's own type errors,
this error is generated by Node.js's C++ and JavaScript internals before any operation is
attempted — it is a strict guard that prevents incorrect types from reaching native code.
The error message always names the offending argument and states both the expected type and the actual type (or value) that was received. Reading the message carefully tells you exactly what to fix.
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefinedTypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received an instance of PromiseTypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer. Received undefinedTypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer. Received type number (42)TypeError [ERR_INVALID_ARG_TYPE]: The "from" argument must be of type string. Received undefinednpm ERR! code ERR_INVALID_ARG_TYPE
Full Stack Trace Example
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
at new NodeError (node:internal/errors:405:5)
at validateString (node:internal/validators:162:11)
at Object.readFile (node:fs:448:3)
at readConfig (/app/src/config.js:12:6)
at Object.<anonymous> (/app/src/index.js:5:1) {
code: 'ERR_INVALID_ARG_TYPE'
}
The stack trace pinpoints the exact Node.js internal that validated the argument
(validateString), the public API that was called (Object.readFile),
and the line in your own code that triggered it (config.js:12). Start debugging
at your own code line — that is where the undefined value was passed in.
Common Causes
| Cause | Why it happens |
|---|---|
Passing undefined to an fs function |
The path argument is undefined because an environment variable, config property, or function parameter was never set before the fs.readFile() / fs.writeFile() call. |
__dirname is undefined in ESM modules |
__dirname and __filename are CommonJS globals. In ES modules (.mjs files or "type": "module" in package.json) they do not exist, so passing __dirname to path.resolve() or path.join() passes undefined. |
Passing undefined to path.resolve() or path.join() |
Any argument to path.resolve() or path.join() that is undefined triggers the error. Common when an object property used as a path segment does not exist. |
Missing return value from async function |
An async function that should return a path or data string has no return statement, so it implicitly returns undefined. The caller then passes that undefined to a built-in. |
Forgot await on an async function |
Without await, the variable holds a Promise object instead of the resolved string. Node.js built-ins reject a Promise as an invalid type. The error message says Received an instance of Promise. |
Passing wrong type to stream.write() or response.end() |
A number, object, or array was passed instead of a string or Buffer. Common when a JSON object is passed directly without JSON.stringify(). |
Destructuring from undefined or null |
const { outputPath } = config silently produces undefined when config itself is undefined, or when the key does not exist in the object. |
| Environment variable not set | process.env.OUTPUT_DIR is undefined when the variable is not defined in the shell, .env file, or CI environment. Passed directly to a path argument without a guard. |
| npm / build tool config issue | The "main" field in package.json is missing or points to a non-existent file, causing npm's internal path resolution to pass undefined to a file system call. |
| React / Create React App (react-scripts) | An outdated react-scripts version passes an undefined path to a webpack or file-system function during build. Upgrading react-scripts resolves it. |
Fix 1 – Check the value before passing it
The fastest way to diagnose the error is to log or assert the value immediately before the failing call. This confirms what is actually being passed so you can trace it upstream.
const fs = require('fs');
// Bad: passes undefined to fs.readFile without any check
fs.readFile(config.inputPath, 'utf8', (err, data) => { /* ... */ });
// Good: log the value before the call to see what it actually is
console.log('inputPath =', config.inputPath);
fs.readFile(config.inputPath, 'utf8', (err, data) => { /* ... */ });
// Better: assert it is a string and fail with a descriptive message
const assert = require('assert');
assert.strictEqual(typeof config.inputPath, 'string',
`config.inputPath must be a string, got ${typeof config.inputPath}: ${config.inputPath}`);
fs.readFile(config.inputPath, 'utf8', (err, data) => { /* ... */ });
Fix 2 – Fix __dirname in ES Modules (ESM)
__dirname and __filename are CommonJS-only globals. When your
file uses ES module syntax (import/export) — either with a
.mjs extension or with "type": "module" in package.json
— these globals are not available. Passing the bare name __dirname to
path.resolve() or path.join() passes undefined,
triggering ERR_INVALID_ARG_TYPE.
// WRONG – __dirname is not defined in ESM; this passes undefined to path.resolve
// TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
import path from 'path';
const configPath = path.resolve(__dirname, 'config.json'); // ReferenceError or undefined
// CORRECT – recreate __dirname using import.meta.url
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const configPath = path.resolve(__dirname, 'config.json'); // works correctly
__dirname pattern is one of the most common
causes of ERR_INVALID_ARG_TYPE in modern Node.js projects that have migrated
from CommonJS to ES modules. Whenever you see the error on a path.resolve()
or path.join() call, check the module system first.
Fix 3 – Validate environment variables at startup
Environment variables are one of the most common sources of undefined.
Rather than letting process.env.X silently propagate through your code,
validate all required variables when the application starts and throw a descriptive
error immediately.
// config.js – validate env vars at startup, not at the point of use
function requireEnv(name) {
const value = process.env[name];
if (typeof value !== 'string' || value.trim() === '') {
throw new Error(
`Missing required environment variable: ${name}\n` +
`Set it in your .env file or shell before starting the application.`
);
}
return value;
}
module.exports = {
outputDir: requireEnv('OUTPUT_DIR'),
databaseUrl: requireEnv('DATABASE_URL'),
apiKey: requireEnv('API_KEY'),
};
// index.js – any ERR_INVALID_ARG_TYPE from a missing env var is now caught here
const config = require('./config');
// If OUTPUT_DIR is not set, you get a clear error at startup, not deep in fs code.
Fix 4 – Use nullish coalescing for defaults
When a config value or function argument is optional, use the ?? operator
to supply a default instead of letting undefined reach a built-in function.
You can also use the logical OR operator (||) for any falsy value.
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs/promises';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
async function writeOutput(data, options = {}) {
// ?? prevents undefined from reaching built-ins when a config key is omitted
const filePath = options.outputPath ?? path.resolve(__dirname, 'output.json');
const encoding = options.encoding ?? 'utf8';
// filePath is always a string now
await fs.writeFile(filePath, JSON.stringify(data, null, 2), encoding);
}
// Also works for path.resolve — guard every segment that could be undefined
const obj = {};
const resolved = path.resolve(obj.basePath || __dirname, 'dist'); // safe fallback
Fix 5 – Fix missing await (Promise passed as string)
When an async function returns a string, forgetting await means the
caller receives a Promise instead. Node.js built-ins will reject it as
the wrong type. The error message will explicitly say
Received an instance of Promise.
const fs = require('fs/promises');
async function getConfigPath() {
// Simulates async config lookup (database, remote config service, etc.)
return '/etc/myapp/config.json';
}
// WRONG – missing await: configPath is a Promise, not a string
// TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string.
// Received an instance of Promise
async function loadConfigBad() {
const configPath = getConfigPath(); // forgot await
return fs.readFile(configPath, 'utf8');
}
// CORRECT – await the async function to get the resolved string
async function loadConfigGood() {
const configPath = await getConfigPath(); // resolves to '/etc/myapp/config.json'
return fs.readFile(configPath, 'utf8');
}
Received an instance of Promise in the error
message, a missing await is almost certainly the cause. Search for the variable
assignment and confirm that every async call is properly awaited.
Fix 6 – Serialize objects before writing (data / chunk argument)
When passing data to fs.writeFile(), stream.write(), or
response.end(), the value must be a string or a Buffer.
Passing a plain JavaScript object, array, or number triggers the
"data" argument must be of type string or an instance of Buffer variant.
const fs = require('fs/promises');
const http = require('http');
// WRONG – passing an object to fs.writeFile causes ERR_INVALID_ARG_TYPE
// TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string
// or an instance of Buffer, TypedArray, or DataView. Received an instance of Object
const results = { count: 42, items: ['a', 'b'] };
await fs.writeFile('output.json', results); // Error!
// CORRECT – serialize to string first
await fs.writeFile('output.json', JSON.stringify(results, null, 2), 'utf8');
// WRONG – passing a number to stream.write
// TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string
// or an instance of Buffer. Received type number (42)
http.createServer((req, res) => {
const statusCode = 200;
res.end(statusCode); // Error!
// CORRECT – convert to string first
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ status: statusCode }));
}).listen(3000);
Fix 7 – npm ERR! code ERR_INVALID_ARG_TYPE during npm install or run
When the error appears in npm output rather than your own code, the cause is usually
a misconfigured package.json, a corrupted npm cache, or an outdated npm
version. The "from" argument must be of type string variant specifically
appears during npm dependency resolution when a package path cannot be determined.
# Step 1: Check your package.json for a valid "main" field
# If "main" points to a file that does not exist, npm throws ERR_INVALID_ARG_TYPE internally
grep '"main"' package.json
# Step 2: Clear the npm cache
npm cache clean --force
# Step 3: Delete node_modules and package-lock.json, then reinstall
rm -rf node_modules package-lock.json
npm install
# Step 4: Update npm to the latest version
npm install -g npm@latest
npm --version
# Step 5: If using Node.js engines field, make sure your Node.js version matches
node --version
grep '"node"' package.json
package.json has a
"main" field pointing to a file path that does not exist or is set to
null/undefined, npm's internal resolver will pass that
non-string value to a file system function and throw ERR_INVALID_ARG_TYPE.
Verify the path is correct or remove the field entirely to use the default
(index.js).
Fix 8 – React / Create React App build error
In React projects bootstrapped with Create React App, ERR_INVALID_ARG_TYPE
during npm start or npm run build is almost always caused by
an outdated react-scripts package. An old version may pass an undefined path
to webpack's file-system resolver.
# Upgrade react-scripts to the latest version
npm install react-scripts@latest
# If the error persists, clear all caches and reinstall from scratch
rm -rf node_modules package-lock.json
npm install
# For ejected Create React App, check webpackDevServer.config.js
# Look for any path that might be constructed from an undefined variable
grep -n "undefined\|resolve\|join" config/webpackDevServer.config.js
Fix 9 – Type check with typeof (external data / user input)
When accepting values from external sources — user input, API responses, parsed JSON — validate the type explicitly before passing them to Node.js built-ins. Consider using TypeScript to catch these issues at compile time instead of at runtime.
const fs = require('fs/promises');
// Guard against wrong types from external callers
async function readUserFile(filePath) {
if (typeof filePath !== 'string') {
throw new TypeError(
`readUserFile: filePath must be a string, got ${typeof filePath} (${String(filePath)})`
);
}
if (filePath.trim() === '') {
throw new RangeError('readUserFile: filePath must not be an empty string');
}
return fs.readFile(filePath, 'utf8');
}
// TypeScript equivalent – catches ERR_INVALID_ARG_TYPE at compile time
// function readUserFile(filePath: string): Promise<string> {
// return fs.readFile(filePath, 'utf8');
// }
Debugging Checklist
- Read the error message — the argument name (
"path","data","chunk","from") tells you exactly which parameter is wrong. - Find the line number in your own code from the stack trace (not the
node:internal/frames) and add aconsole.logto print the value. - If the value is
undefined, trace back to where it was set: config object, environment variable, function return value, or destructured property. - If the value is a
Promiseobject (Received an instance of Promise), add a missingawaitbefore the async function call. - If using ES modules and the error is on
path.resolve()orpath.join(), check whether__dirnameis defined — it is not available in ESM. UsefileURLToPath(import.meta.url)instead. - If the value is an object or number being passed to
stream.write()orresponse.end(), wrap it withJSON.stringify()orString(). - If the error appears in npm output, check
package.jsonfor a broken"main"field, clear the npm cache, and update npm. - Use
NODE_DEBUG=fsto trace all file system calls and see what path value is actually being passed at the system level.
# Trace all fs calls to see the exact path argument values Node.js is using
NODE_DEBUG=fs node app.js 2>&1 | head -40
String(value)
on everything to suppress the error hides the real problem. If value is
undefined, String(undefined) produces the literal string
"undefined", which will cause a different error (e.g. ENOENT: no such
file or directory 'undefined'). Find why the value is undefined and
fix the root cause instead.
Frequently Asked Questions
What is ERR_INVALID_ARG_TYPE in Node.js?
ERR_INVALID_ARG_TYPE is a TypeError thrown by Node.js built-in functions when they receive an argument of the wrong JavaScript type. The most common case is passing undefined to a function that expects a string, such as passing an undefined path to fs.readFile(), fs.writeFile(), or path.resolve(). The error message always names the argument and states both the expected and received types.
How do I fix: The "path" argument must be of type string. Received undefined?
This means the variable you passed as the file path is undefined. Add a console.log right before the failing call to confirm the value, then trace it back to its source:
- Environment variable not set:
process.env.OUTPUT_DIRisundefinedwhen missing from.envor CI settings. - Missing config property: Use
const p = config.path ?? './default'to provide a fallback. - ESM module:
__dirnameis undefined — usefileURLToPath(import.meta.url). - Missing await: Add
awaitbefore the async call that returns the path.
Why does it say "Received an instance of Promise"?
This is caused by a missing await keyword. Without await, the variable holds an unresolved Promise object instead of the actual string value. Find the assignment and add the missing await:
// Wrong
const configPath = getConfigPath(); // returns Promise, not string
// Correct
const configPath = await getConfigPath(); // resolves to string
How do I fix __dirname causing ERR_INVALID_ARG_TYPE in ESM?
__dirname is not defined in ES modules. Use fileURLToPath from the built-in url module to recreate it:
import { fileURLToPath } from 'url';
import path from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
How do I fix npm ERR! code ERR_INVALID_ARG_TYPE during npm install?
Run these steps in order until the error resolves:
- Check
package.json— ensure the"main"field points to a file that actually exists. - Clear the npm cache:
npm cache clean --force - Delete
node_modulesandpackage-lock.json, then runnpm installagain. - Update npm:
npm install -g npm@latest
How do I fix ERR_INVALID_ARG_TYPE in a React / Create React App project?
An outdated react-scripts package is the most common cause in CRA projects. Run:
npm install react-scripts@latest
If that does not fix it, delete node_modules and package-lock.json and run npm install again. For ejected apps, inspect config/webpackDevServer.config.js for any path built from a potentially undefined variable.
Why does "The data argument must be of type string or an instance of Buffer" appear?
This variant is thrown by fs.writeFile(), stream.write(), and similar APIs when you pass an object, array, or number instead of a string or Buffer. Serialize the value first:
// Object → JSON string
await fs.writeFile('out.json', JSON.stringify(data, null, 2), 'utf8');
// Number → string
stream.write(String(count));
// Buffer for binary data
stream.write(Buffer.from(binaryData));
Related Errors
TypeError: Cannot read properties of undefined— accessing a property on an undefined value; often the same root cause (missing env var or unresolved async) manifesting one step earlierError: Cannot find module (MODULE_NOT_FOUND)— a related npm/require failure often caused by the same broken package.json configurationENOENT: no such file or directory— what you see after usingString(undefined)as a workaround, producing the literal path"undefined"ERR_REQUIRE_ESM— related ESM migration error that often surfaces alongside__dirnameissuesUnhandledPromiseRejection— if a missingawaitcausesERR_INVALID_ARG_TYPEinside an async function without a try/catch, it surfaces as this errorERR_INVALID_ARG_VALUE— sibling error thrown when the argument is the right type but an invalid value (e.g. a negative number for a buffer size)ERR_MISSING_ARGS— thrown when a required argument is omitted entirely rather than passed as the wrong type