Skip to content

Bug: ESLint crashes with --permission when it tries to delete cache #19647

@regseb

Description

@regseb

Environment

Node version: v22.13.1
npm version: 11.2.0
Local ESLint version: 9.25.1
Global ESLint version: no
Operating System: Ubuntu 22.04.5 LTS

What parser are you using?

Default (Espree)

What did you do?

  • package.json

    {
      "name": "testcase",
      "version": "0.0.0",
      "dependencies": {
        "eslint": "9.25.1"
      }
    }
  • index.js

    console.log("foo");
  • lint.js

    import { ESLint } from "eslint";
    
    const eslint = new ESLint({ overrideConfigFile: true });
    const results = await eslint.lintFiles(["index.js"]);
  1. npm install
  2. node --permission --allow-fs-read '*' lint.js

What did you expect to happen?

ESLint doesn't crash.

What actually happened?

node:internal/fs/promises:1064
  return await PromisePrototypeThen(
               ^

TypeError: Method Promise.prototype.then called on incompatible receiver undefined
    at then (<anonymous>)
    at Object.unlink (node:internal/fs/promises:1064:16)
    at ESLint.lintFiles (/home/regseb/testcase/node_modules/eslint/lib/eslint/eslint.js:706:14)
    at file:///home/regseb/testcase/lint.js:4:30
    at ModuleJob.run (node:internal/modules/esm/module_job:271:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:547:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:116:5)

Node.js v22.13.1

Link to Minimal Reproducible Example

See What did you do?

https://eslint.org/play/#eyJ0ZXh0Ij...I6e319fX19

Participation

  • I am willing to submit a pull request for this issue.

Additional comments

eslint/lib/eslint/eslint.js

Lines 701 to 718 in 3ed4b36

// Delete cache file; should this be done here?
if (!cache && cacheFilePath) {
debug(`Deleting cache file at ${cacheFilePath}`);
try {
await fs.unlink(cacheFilePath);
} catch (error) {
const errorCode = error && error.code;
// Ignore errors when no such file exists or file system is read only (and cache file does not exist)
if (
errorCode !== "ENOENT" &&
!(errorCode === "EROFS" && !existsSync(cacheFilePath))
) {
throw error;
}
}
}

I try to run linters with read-only permissions, but ESLint crashes. ESLint tries to delete the cache (which doesn't exist), but it doesn't have write access: so Node doesn't give it permission.

I think ESLint should delete the cache only if it exists. Or check for permission (need Node v20+): process.permission.has("fs.write", cacheFilePath). Adding a condition to the catch seems difficult, as it's hard to identify this error. It's an instance of TypeError and has no code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedThere is consensus among the team that this change meets the criteria for inclusionbugESLint is working incorrectlycoreRelates to ESLint's core APIs and featuresrepro:yesIssues with a reproducible example

    Type

    No type

    Projects

    Status

    Complete

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions