santifer/career-ops · error · TypeError
isMainModule expects import.meta.url (a file: URL), got a fi
Error message
isMainModule expects import.meta.url (a file: URL), got a filesystem path: ${moduleUrl}. Returning false here would silently suppress the CLI, which is the defect #3170 fixed. What it means
After the string checks, isMainModule() detects filesystem paths (e.g. '/usr/app/cli.mjs' or 'C:\co\pdf.mjs') and throws a TypeError instead of silently returning false. A path compares unequal to the entry module URL, so returning false would make the module's CLI tail never run while the process exits 0 — the exact silent-suppression bug (#3170) this module exists to prevent. Throwing names the mistake loudly at the call site.
Source
Thrown at lib/is-main-module.mjs:100
}
if (!moduleUrl.startsWith('file:')) {
// A Windows drive letter parses as a one-character URL scheme, so it has to
// be excluded before the scheme test or `C:\co\pdf.mjs` reads as a URL.
//
// Matched WITHOUT requiring a following separator, because `C:repo\pdf.mjs`
// is also a path — the drive-RELATIVE form, resolved against the current
// directory on C:. Requiring `[\\/]` let that one through to the `return
// false` below, which is the silent-suppression footgun this branch exists
// to prevent. No registered URL scheme is a single letter, so treating
// `X:` as a drive is unambiguous.
const isPath = !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(moduleUrl) || /^[a-zA-Z]:/.test(moduleUrl);
if (isPath) {
// LOUD, because the quiet alternative is the bug this module exists to
// kill. `isMainModule(import.meta.filename)` would resolve, compare
// false, skip the CLI tail, and exit 0 having printed nothing — #3170
// reintroduced one argument at a time. A crash names the mistake instead.
throw new TypeError(
`isMainModule expects import.meta.url (a file: URL), got a filesystem path: ${moduleUrl}. ` +
'Returning false here would silently suppress the CLI, which is the defect #3170 fixed.',
);
}
// A real non-file scheme (`data:`, `node:`, an http import). Not a
// programmer error, and never the file named on the command line.
return false;
}
// No argv[1] at all: `node -e`, `node --input-type=module`, a worker, the
// REPL. Nothing was "run" in the sense the guard means. Checked AFTER the
// argument validation so a bad call is caught wherever it happens.
if (!process.argv[1]) return false;
let modulePath;
try {
modulePath = fileURLToPath(moduleUrl);
} catch {View on GitHub (pinned to 1696bec4d0)
Solutions
- Pass `import.meta.url` verbatim: `isMainModule(import.meta.url)`
- Remove any path.resolve()/fileURLToPath() conversion before the call
- On Windows, ensure you are not stripping or mangling the file: scheme before the call
Example fix
// before
if (isMainModule(path.resolve(process.argv[1]))) { cli(); }
// after
if (isMainModule(import.meta.url)) { cli(); } Defensive patterns
Strategy: type-guard
Validate before calling
const u = import.meta.url; if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(u) && u.startsWith('file:')) isMainModule(u); Type guard
const isFileUrl = (v) => typeof v === 'string' && v.startsWith('file:'); Try / catch
try { main = isMainModule(import.meta.url); } catch (e) { console.error('isMainModule misuse:', e.message); process.exitCode = 1; } Prevention
- Grep the codebase for isMainModule( and confirm every call site passes import.meta.url literally
- Never pass import.meta.filename, __filename, or argv[1]
- On Windows be extra careful: drive letters make paths look URL-like
When it happens
Trigger: Calling isMainModule(import.meta.filename), isMainModule(__filename), or isMainModule(process.argv[1]) — any argument that is a filesystem path rather than a `file:` URL. Detection: no valid URL scheme, or a Windows drive-letter prefix.
Common situations: Porting code from CommonJS where __filename was the idiom; mixing up import.meta.url vs import.meta.filename; resolving the path with path.resolve() before passing it in; Windows drive letters accidentally reading as a one-char URL scheme.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01).
Data as JSON: /api/errors/e8e6a0c20c56ea0a.
Report an issue: GitHub.