Node.js ERR_INVALID_ARG_TYPE - Fix "argument must be of type string"
ERR_INVALID_ARG_TYPE is Node’s core APIs validating their inputs. It almost always means a value that should be a string/Buffer arrived as undefined - a missing env var, an unresolved path, or a misread config.
What this error means
A script crashes with TypeError [ERR_INVALID_ARG_TYPE], typically "The \"path\" argument must be of type string. Received undefined", in a fs/path call. It frequently fires only in CI, where an env var or config value is unset.
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type
string or an instance of Buffer or URL. Received undefined
at fs.readFileSync (node:fs)
at loadConfig (/app/scripts/build.js:12:18)
code: 'ERR_INVALID_ARG_TYPE'Diagnose it: what is different about the runner?
A build that passes locally and fails on a runner differs in a small number of predictable ways. Check those before changing build configuration, because the build config is usually not the thing that changed.
- run: |
node --version && npm --version
echo "NODE_ENV=$NODE_ENV CI=$CI"
nproc && free -h && df -h /
ls -la node_modules/.bin | headCommon causes
A required env var is undefined in CI
Code passes process.env.SOMETHING straight into a path/fs call. The var is set locally but missing in the CI job, so undefined reaches the API.
An async/optional value used before it resolves
A path computed from a promise, argv, or config that came back empty is forwarded to a core API, which rejects the wrong type.
How to fix it
Validate inputs and surface the real cause
Fail fast with a clear message instead of letting undefined reach a core API.
const dir = process.env.OUTPUT_DIR
if (typeof dir !== 'string' || !dir) {
throw new Error('OUTPUT_DIR is not set')
}
fs.readFileSync(path.join(dir, 'config.json'))Set the missing CI value
- Identify which argument is undefined from the trace, then trace it to its source.
- Provide the missing env var/secret or argv in the workflow.
- Add a default or guard so the failure is explicit, not a cryptic type error.
The three that account for most of them
- Case sensitivity. Linux runners are case sensitive, macOS is not. An import with the wrong case resolves locally and fails in CI.
- Out of memory. Exit code 137 is a SIGKILL from the kernel, not a build error. Raise
--max-old-space-sizeor use a larger runner. - devDependencies pruned.
NODE_ENV=productionmakesnpm ciskip devDependencies, so the build tool itself goes missing. Set it after install, not before.
How to prevent it
- Validate required env vars at startup with clear errors.
- Keep CI env parity with local for required values.
- Guard core-API arguments rather than passing values through blindly.