#26693·oxc

linter: `import/default` gives inconsistent results for identical import patterns depending on the target file's module syntax

Author: finalwhyCreated Sep 15, 2026Updated Sep 16, 2026
LabelsA-linter

What version of Oxlint are you using?

1.76.0

What command did you run?

oxlint -c .oxlintrc.json src/

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

{
  "plugins": ["import"],
  "rules": { "import/default": "error" }
}

What happened?

Two imports of the exact same shape produce different diagnostics. This is a Vite project, where both files are imported as ?worker virtual modules:

// src/utils/download.ts
import CsvDataWorker from '@/worker/handleData2Csv.worker?worker';
import XlsxDataWorker from '@/worker/handleData2Xlxs.worker?worker';

Only the first one is reported:

src/utils/download.ts:10:8: warning import(default): No default export found in imported module "@/worker/handleData2Csv.worker?worker"

The second line is silent.

Root cause

The difference is only in the target files, and it is not about the ?worker query:

  • handleData2Csv.worker.ts contains an import statement → Oxlint builds a module record for it → import/default checks it → no default export → reports.
  • handleData2Xlxs.worker.ts contains no import or export at all (a plain script with self.onmessage = ...) → the rule silently skips it, even though it equally has no default export.

Minimal reproduction without Vite (3 files):

// probeA.ts — has an import
import { rowsToCsv } from './rowsToCsv';
console.log(rowsToCsv);
// probeB.ts — no import/export
self.onmessage = () => {};
// entry.ts
import A from './probeA';
import B from './probeB';
console.log(A, B);

Result: probeA is reported, probeB is not. Adding any import statement (even unused) to probeB makes it report too. Same behavior with and without the ?worker query; the query is not the trigger.

Why this matters

  1. False positive for bundler virtual modules: ?worker, ?raw, ?url, ?inline modules get a synthetic default export from Vite at build time. Static analysis cannot see it, so whenever the underlying file is an ES module, import/default reports a false positive. (import/no-unresolved was deliberately not implemented for this class of reason — #1117.)
  2. Non-deterministic diagnostics: identical import patterns produce different results depending on whether the target file happens to contain an import/export statement. Unrelated edits elsewhere (adding an import to the worker file) silently turn the diagnostic on/off, which is confusing and hard to suppress predictably.

Expected

  • Ideally: skip import/* export-shape checking for specifiers that carry bundler query suffixes (or otherwise cannot be resolved to a plain source file), since the real module is generated by the bundler.
  • At minimum: make the behavior consistent — if a target module has no ESM syntax, either always report (it truly has no default export) or always skip, not "report only if it looks like a module".

Related

  • #23731 — import/default false positive when importing a default type from an external package (different trigger, same rule).
  • #1117 — import/no-unresolved intentionally not implemented because module resolution produces false positives.

Environment

macOS (darwin), oxlint 1.76.0, TS project with tsconfig path aliases (@/*), no custom resolvers.