In a sandboxed environment, import-x/no-unresolved can throw EPERM during its case-sensitive filename check when a resolved import is outside process.cwd().
In our project, backend lint runs from backend/, while TypeScript path aliases resolve shared/* imports to ../shared/*:
tsconfig.json:
{
"compilerOptions": {
"paths": {
"shared/*": ["../shared/*"]
}
}
}
The import resolves correctly, but after resolution fileExistsWithCaseSync() recursively reads parent directories with fs.readdirSync(dir) to verify filename casing. Because process.cwd() is backend/ and is not an ancestor of files in ../shared, that upward walk can continue above the repo root. In a sandboxed environment, reading above the repo is intentionally blocked, so lint crashes.
Error
Error: EPERM: operation not permitted, scandir '/Users/.../source'
Occurred while linting .../backend/src/db/account.db.ts
Rule: "import-x/no-unresolved"
at Object.readdirSync (node:fs:1569:26)
at fileExistsWithCaseSync (.../node_modules/eslint-plugin-import-x/lib/utils/resolve.js:41:30)
at fileExistsWithCaseSync (.../node_modules/eslint-plugin-import-x/lib/utils/resolve.js:43:15)
Expected behavior
no-unresolved should not crash the lint run when the import resolved successfully but the extra casing check cannot read an ancestor directory.
Fix options
One possible fix would be to catch EPERM / EACCES during the casing check and either stop checking ancestors or report a normal lint diagnostic instead of throwing.
Workaround
This fixes it for us:
'import-x/no-unresolved': [
'error',
{
caseSensitive: false,
},
],
That keeps unresolved-import checking enabled, but disables the extra filename-casing check.
Versions
- eslint-plugin-import-x: 4.16.2
- eslint: 10.4.0
- @eslint/js: 10.0.1
- typescript-eslint: 8.59.4
- eslint-plugin-simple-import-sort: 13.0.0
- node: 24.14.0
- OS: macOS
In a sandboxed environment,
import-x/no-unresolvedcan throwEPERMduring its case-sensitive filename check when a resolved import is outsideprocess.cwd().In our project, backend lint runs from
backend/, while TypeScript path aliases resolveshared/*imports to../shared/*:tsconfig.json:
The import resolves correctly, but after resolution
fileExistsWithCaseSync()recursively reads parent directories withfs.readdirSync(dir)to verify filename casing. Becauseprocess.cwd()isbackend/and is not an ancestor of files in../shared, that upward walk can continue above the repo root. In a sandboxed environment, reading above the repo is intentionally blocked, so lint crashes.Error
Error: EPERM: operation not permitted, scandir '/Users/.../source' Occurred while linting .../backend/src/db/account.db.ts Rule: "import-x/no-unresolved" at Object.readdirSync (node:fs:1569:26) at fileExistsWithCaseSync (.../node_modules/eslint-plugin-import-x/lib/utils/resolve.js:41:30) at fileExistsWithCaseSync (.../node_modules/eslint-plugin-import-x/lib/utils/resolve.js:43:15)Expected behavior
no-unresolvedshould not crash the lint run when the import resolved successfully but the extra casing check cannot read an ancestor directory.Fix options
One possible fix would be to catch
EPERM/EACCESduring the casing check and either stop checking ancestors or report a normal lint diagnostic instead of throwing.Workaround
This fixes it for us:
That keeps unresolved-import checking enabled, but disables the extra filename-casing check.
Versions