Skip to content

linter: Runaway CPU usage (~280%) and apparent infinite loop via NAPI binding #21265

@erictheswift

Description

@erictheswift

What version of Oxlint are you using?

1.58.0 (@oxlint/binding-darwin-arm64)

What command did you run?

Not invoked directly — oxlint runs as a language server via the https://plugins.jetbrains.com/plugin/27061-oxc v0.0.26 in WebStorm. The plugin spawns a node process that loads @oxlint/binding-darwin-arm64@1.58.0/oxlint.darwin-arm64.node as a NAPI binding and communicates over LSP

What does your .oxlintrc.json (or oxlint.config.ts) config file look like?

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "plugins": ["react", "import", "jsx-a11y", "unicorn", "typescript"],
  "categories": {
    "correctness": "off"
  },
  "env": {
    "builtin": true,
    "browser": true,
    "es2024": true,
    "jest": true,
    "node": true
  },
  "ignorePatterns": [
    "**/node_modules/**",
    "**/dist/**",
    "**/coverage/**",
    "**/build/**",
    "**/lib/**",
    "**/*.d.ts",
    "packages/formulas/**/generated/**"
  ],
  "rules": {
    "constructor-super": "error",
    "for-direction": "error",
    "no-async-promise-executor": "error",
    "no-case-declarations": "error",
    "no-class-assign": "error",
    "no-compare-neg-zero": "error",
    "no-cond-assign": ["warn", "except-parens"],
    "no-const-assign": "warn",
    "no-constant-binary-expression": "error",
    "no-constant-condition": "error",
    "no-control-regex": "warn",
    "no-debugger": "warn",
    "no-delete-var": "warn",
    "no-dupe-class-members": "warn",
    "no-dupe-else-if": "error",
    "no-dupe-keys": "warn",
    "no-duplicate-case": "warn",
    "no-empty": "error",
    "no-empty-character-class": "warn",
    "no-empty-pattern": "warn",
    "no-empty-static-block": "error",
    "no-ex-assign": "warn",
    "no-extra-boolean-cast": "error",
    "no-fallthrough": "warn",
    "no-func-assign": "warn",
    "no-global-assign": "warn",
    "no-import-assign": "error",
    "no-invalid-regexp": "warn",
    "no-irregular-whitespace": "error",
    "no-loss-of-precision": "error",
    "no-new-native-nonconstructor": "warn",
    "no-nonoctal-decimal-escape": "error",
    "no-obj-calls": "warn",
    "no-prototype-builtins": "error",
    "no-redeclare": "warn",
    "no-regex-spaces": "warn",
    "no-self-assign": "warn",
    "no-setter-return": "error",
    "no-shadow-restricted-names": "warn",
    "no-sparse-arrays": "warn",
    "no-this-before-super": "warn",
    "no-unexpected-multiline": "warn",
    "no-unsafe-finally": "error",
    "no-unsafe-negation": "warn",
    "no-unsafe-optional-chaining": "error",
    "no-unused-labels": "warn",
    "no-unused-private-class-members": "error",
    "no-unused-vars": [
      "warn",
      {
        "args": "none",
        "varsIgnorePattern": "^_",
        "caughtErrors": "none",
        "ignoreRestSiblings": true
      }
    ],
    "no-useless-backreference": "error",
    "no-useless-catch": "error",
    "no-useless-escape": "warn",
    "no-with": "warn",
    "require-yield": "warn",
    "use-isnan": "warn",
    "valid-typeof": "warn",
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn",
    "no-console": "error",
    "array-callback-return": "warn",
    "default-case": [
      "warn",
      {
        "commentPattern": "^no default$"
      }
    ],
    "eqeqeq": ["warn"],
    "no-array-constructor": "warn",
    "no-caller": "warn",
    "no-eval": "warn",
    "no-extend-native": "warn",
    "no-extra-bind": "warn",
    "no-extra-label": "warn",
    "no-implicit-coercion": [
      "warn",
      {
        "boolean": true,
        "string": true,
        "number": true
      }
    ],
    "no-iterator": "warn",
    "no-label-var": "warn",
    "no-labels": [
      "warn",
      {
        "allowLoop": true,
        "allowSwitch": false
      }
    ],
    "no-lone-blocks": "warn",
    "no-loop-func": "warn",
    "no-multi-str": "warn",
    "no-new-func": "warn",
    "no-object-constructor": "warn",
    "no-new-wrappers": "warn",
    "no-script-url": "warn",
    "no-self-compare": "warn",
    "no-sequences": "warn",
    "no-template-curly-in-string": "warn",
    "no-throw-literal": "warn",
    "no-restricted-globals": ["error"],
    "no-unused-expressions": [
      "error",
      {
        "allowShortCircuit": true,
        "allowTernary": true,
        "allowTaggedTemplates": true
      }
    ],
    "no-useless-computed-key": "warn",
    "no-useless-concat": "warn",
    "no-useless-constructor": "warn",
    "no-useless-rename": [
      "warn",
      {
        "ignoreDestructuring": false,
        "ignoreImport": false,
        "ignoreExport": false
      }
    ],
    "no-var": "warn",
    "no-inner-declarations": "warn",
    "no-param-reassign": "warn",
    "no-void": "warn",
    "prefer-object-has-own": "warn",
    "max-lines": ["warn", 500],
    "import/first": "error",
    "import/no-amd": "error",
    "import/no-webpack-loader-syntax": "error",
    "import/no-self-import": "error",
    "react/jsx-no-comment-textnodes": "warn",
    "react/jsx-no-duplicate-props": "warn",
    "react/jsx-no-target-blank": "warn",
    "react/jsx-no-undef": "error",
    "react/jsx-pascal-case": [
      "warn",
      {
        "allowAllCaps": true,
        "ignore": []
      }
    ],
    "react/no-danger-with-children": "warn",
    "react/no-direct-mutation-state": "warn",
    "react/no-is-mounted": "warn",
    "react/style-prop-object": "warn",
    "react/button-has-type": "error",
    "jsx-a11y/alt-text": "warn",
    "jsx-a11y/anchor-has-content": "warn",
    "jsx-a11y/anchor-is-valid": [
      "warn",
      {
        "aspects": ["noHref", "invalidHref"]
      }
    ],
    "jsx-a11y/aria-activedescendant-has-tabindex": "warn",
    "jsx-a11y/aria-props": "warn",
    "jsx-a11y/aria-proptypes": "warn",
    "jsx-a11y/aria-role": "warn",
    "jsx-a11y/aria-unsupported-elements": "warn",
    "jsx-a11y/heading-has-content": "warn",
    "jsx-a11y/iframe-has-title": "warn",
    "jsx-a11y/img-redundant-alt": "warn",
    "jsx-a11y/no-access-key": "warn",
    "jsx-a11y/no-distracting-elements": "warn",
    "jsx-a11y/no-redundant-roles": "warn",
    "jsx-a11y/role-has-required-aria-props": "warn",
    "jsx-a11y/role-supports-aria-props": "warn",
    "jsx-a11y/scope": "warn",
    "no-unreachable": "warn",
    "getter-return": "warn",
    "no-use-before-define": [
      "warn",
      {
        "functions": false,
        "classes": false,
        "variables": false
      }
    ],
    "no-implied-eval": "warn",
    "dot-notation": "warn",
    "consistent-return": "warn",
    "react/require-render-return": "error",
    "curly": ["warn", "all"],
    "@typescript-eslint/no-explicit-any": "error"
  },
  "globals": {
    "jasmine": "readonly"
  },
  "overrides": [
    {
      "files": ["**/test-data/**", "**/function-descriptors/**", "**/__tests__/**"],
      "rules": {
        "max-lines": "off"
      }
    },
    {
      "files": ["**/*.test.*", "**/*.spec.*", "**/__tests__/**", "**/config/jest/**"],
      "rules": {
        "no-extend-native": "off"
      }
    },
    {
      "files": ["**/*.ts", "**/*.tsx"],
      "rules": {
        "constructor-super": "off",
        "no-class-assign": "off",
        "no-const-assign": "off",
        "no-dupe-class-members": "off",
        "no-dupe-keys": "off",
        "no-func-assign": "off",
        "no-import-assign": "off",
        "no-new-native-nonconstructor": "off",
        "no-obj-calls": "off",
        "no-redeclare": "off",
        "no-setter-return": "off",
        "no-this-before-super": "off",
        "no-unsafe-negation": "off",
        "no-var": "error",
        "no-with": "off",
        "prefer-const": "error",
        "prefer-rest-params": "error",
        "prefer-spread": "error",
        "@typescript-eslint/ban-ts-comment": "error",
        "no-array-constructor": "error",
        "@typescript-eslint/no-duplicate-enum-values": "error",
        "@typescript-eslint/no-empty-object-type": "off",
        "@typescript-eslint/no-extra-non-null-assertion": "error",
        "@typescript-eslint/no-misused-new": "error",
        "@typescript-eslint/no-namespace": "error",
        "@typescript-eslint/no-non-null-asserted-optional-chain": "error",
        "@typescript-eslint/no-require-imports": "error",
        "@typescript-eslint/no-this-alias": "error",
        "@typescript-eslint/no-unnecessary-type-constraint": "error",
        "@typescript-eslint/no-unsafe-declaration-merging": "error",
        "@typescript-eslint/no-unsafe-function-type": "error",
        "no-unused-expressions": [
          "error",
          {
            "allowShortCircuit": true,
            "allowTernary": true,
            "allowTaggedTemplates": true
          }
        ],
        "no-unused-vars": [
          "error",
          {
            "args": "after-used",
            "argsIgnorePattern": "^_",
            "varsIgnorePattern": "^_",
            "caughtErrors": "none",
            "ignoreRestSiblings": true
          }
        ],
        "@typescript-eslint/no-wrapper-object-types": "error",
        "@typescript-eslint/prefer-as-const": "error",
        "@typescript-eslint/prefer-namespace-keyword": "error",
        "@typescript-eslint/triple-slash-reference": "error",
        "@typescript-eslint/no-empty-interface": "off",
        "no-useless-constructor": ["error"]
      }
    },
    {
      "files": [
        "packages/e-u/**/*.ts",
        "packages/e-u/**/*.tsx",
        "packages/p-s/**/*.ts",
        "packages/p-s/**/*.tsx",
        "packages/t-e/**/*.ts",
        "packages/t-e/**/*.tsx",
        "server/**/*.ts"
      ],
      "rules": {
        "@typescript-eslint/no-explicit-any": "off"
      }
    },
    {
      "files": ["packages/ns-tl/demo/**", "packages/ns-tl/__tests__/**"],
      "rules": {
        "no-console": "off"
      }
    },
    {
      "files": ["packages/kit/src/icons/**/*"],
      "rules": {
        "unicorn/filename-case": "off"
      }
    },
    {
      "files": ["ns-e2e-tests/**/*.ts"],
      "rules": {
        "no-console": "off",
        "react-hooks/rules-of-hooks": "off",
        "no-restricted-imports": [
          "error",
          {
            "paths": [
              {
                "name": "@playwright/test",
                "importNames": ["test", "expect"],
                "message": "Import 'test' and 'expect' from '@/fixture' instead of directly from '@playwright/test'."
              }
            ]
          }
        ]
      }
    },
    {
      "files": ["packages/automations/**"],
      "rules": {
        "no-restricted-imports": [
          "error",
          {
            "patterns": [
              {
                "group": ["@ns/automations/**"]
              }
            ]
          }
        ]
      }
    },
    {
      "files": ["packages/kit/**"],
      "rules": {
        "no-restricted-imports": [
          "error",
          {
            "patterns": [
              {
                "group": ["@ns/kit/**"]
              }
            ]
          }
        ]
      }
    },
    {
      "files": ["packages/t-e/**"],
      "rules": {
        "no-restricted-imports": [
          "error",
          {
            "patterns": [
              {
                "group": ["@ns/t-e/**"]
              }
            ]
          }
        ]
      }
    },
    {
      "files": ["ns-ui/**"],
      "rules": {
        "no-restricted-imports": [
          "error",
          {
            "patterns": [
              {
                "group": ["ns-ui/**"]
              },
              {
                "group": ["@ns/kit/src/design-system/**"],
                "message": "Caught me naked! Use @ns/kit/src/design-system public API instead."
              },
              {
                "group": ["lodash/fp/**"],
                "message": "Bad type inference. Use lodash/{method} instead."
              }
            ],
            "paths": [
              {
                "name": "react-router",
                "importNames": ["Prompt"],
                "message": "Use Prompt from src/components/common/prompt instead"
              },
              {
                "name": "react-router-dom",
                "importNames": ["Prompt"],
                "message": "Use Prompt from src/components/common/prompt instead"
              },
              {
                "name": "lodash",
                "message": "Not tree-shakeable. Use lodash/{method} instead."
              },
              {
                "name": "lodash/fp",
                "message": "Bad type inference. Use lodash/{method} instead."
              },
              {
                "name": "react-redux",
                "importNames": ["useStore", "useSelector", "useDispatch"],
                "message": "Use typed hooks from src/store/hooks instead."
              },
              {
                "name": "reselect",
                "importNames": ["createSelector", "createStructuredSelector"],
                "message": "Use typed version from src/selector-utils instead."
              }
            ]
          }
        ]
      }
    }
  ]
}

What happened?

The oxlint language server process pegs ~280% CPU (3 ARM64 cores) indefinitely and never returns results. The process was left running for ~2 hours before being killed.

Observed via macOS Activity Monitor at time of sampling:

  ┌──────────────────┬─────────────┐                                                                                                                                                  
  │      Metric      │    Value    │                                                                                                                                                     
  ├──────────────────┼─────────────┤                                                                                                                                                     
  │ CPU              │ 253–284%    │                                                                                                                                                     
  ├──────────────────┼─────────────┤                                                                                                                                                     
  │ CPU time         │ 2:52:24     │                                                                                                                                                     
  ├──────────────────┼─────────────┤                                                                                                                                                  
  │ Real memory      │ 395 MB      │
  ├──────────────────┼─────────────┤
  │ Threads          │ 28          │
  ├──────────────────┼─────────────┤
  │ Context switches │ 155,321,607 │
  ├──────────────────┼─────────────┤
  │ Unix syscalls    │ 522,147,291 │                                                                                                                                                     
  └──────────────────┴─────────────┘                                                                                                                                                     

A macOS sample (1ms interval, 2103 samples) of the process shows:

  • One tokio-rt-worker thread is continuously walking the filesystem — __opendir2, readdir_r, stat syscalls dominate samples. This suggests an unbounded or cyclic directory traversal.
  • Another thread is doing deep recursive work inside oxlint.darwin-arm64.node — open → read → fstat → close cycles on files.
  • 65/2103 samples hit cthread_yield / swtch_pri, indicating thread contention.
  • Most other tokio-rt-worker threads are idle (_pthread_cond_wait), so the runtime is bottlenecked on the FS-walking thread.
  • Two additional tokio-rt-worker threads were spawned mid-run (different thread IDs from the initial pool) but are also idle.

I have the full sample output (~25k lines) available on request.

Environment:

  • oxlint: 1.58.0 (@oxlint/binding-darwin-arm64)
  • oxc IntelliJ plugin: 0.0.26
  • IDE: WebStorm
  • macOS 26.3 (25D125), Apple Silicon (ARM64)
  • Node: managed via n

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-editorArea - Editor and Language ServerA-linterArea - Linter

    Type

    Priority

    None yet

    Effort

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions