oxc-project/oxc · warning

Module {export_name:?} has named export {module_name:?}

Error message

Module {export_name:?} has named export {module_name:?}

What it means

Diagnostic from the oxlint rule import/no-named-as-default (suspicious category). It fires when a default import's local name matches a named export of the source module: e.g. given `foo.js` has `export default 'foo'` and `export const bar = true`, writing `import bar from './foo.js'` is reported. The code works but strongly suggests the author meant the named export and got the default instead — a classic import mistake. Type-only imports, unresolved modules, and the case where default and name are the same re-exported value (`export { foo as default }` alongside `export { foo }`) are skipped.

Source

Thrown at crates/oxc_linter/src/rules/import/no_named_as_default.rs:16

use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{
    context::LintContext,
    module_record::{ExportExportName, ExportImportName, ImportImportName, ModuleRecord},
    rule::Rule,
};

fn no_named_as_default_diagnostic(
    span: Span,
    module_name: &str,
    export_name: &str,
) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Module {export_name:?} has named export {module_name:?}"))
        .with_help(format!("Using default import as {module_name:?} can be confusing. Use another name for default import to avoid confusion."))
        .with_label(span)
}

// <https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-named-as-default.md>
#[derive(Debug, Default, Clone)]
pub struct NoNamedAsDefault;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Reports use of an exported name as the locally imported name of a default export.
    /// This happens when an imported default export is assigned a name that conflicts
    /// with a named export from the same module.
    ///
    /// ### Why is this bad?
    ///
    /// Using a named export's identifier for a default export can cause confusion

View on GitHub (pinned to e1e7af627c)

Solutions

  1. If you meant the named export (most common): change to `import { bar } from './foo.js'`
  2. If you really want the default, rename the local binding to something that does not collide: `import foo from './foo.js'`
  3. Add the named export check to code review for shared modules that mix default and named exports

Example fix

// foo.js
export default 'foo';
export const bar = true;

// before
import bar from './foo.js'; // bar is actually the string 'foo', not the boolean

// after
import { bar } from './foo.js';
Defensive patterns

Strategy: validation

Validate before calling

// keep the suspicious-category rule on in CI (default-enabled set):
// npx oxlint src
// For mixed default+named modules, prefer named exports at the boundary.

Prevention

When it happens

Trigger: run_once iterates import entries; for ImportImportName::Default entries whose local name appears in the remote module's exported_bindings (and the same-reexport check of PR #3032 does not apply), it reports at the import specifier span — crates/oxc_linter/src/rules/import/no_named_as_default.rs:16. Typical: `import bar from './foo.js'` when './foo.js' also named-exports `bar`.

Common situations: IDE auto-import picking the default export but suggesting the named export's name; refactors where a component switches from named to default export and old import sites keep the name; large shared UI/utility modules exposing both defaults and many named exports.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/74dfb9902707f9f9. Report an issue: GitHub.