oxc-project/oxc · warning

Do not import Node.js builtin module `{module_name}`

Error message

Do not import Node.js builtin module `{module_name}`

What it means

Diagnostic from the oxlint rule import/no-nodejs-modules (style category). It fires when a module imports a Node.js builtin — `fs`, `node:path`, `crypto`, etc. — signaling that Node-only code reached a context meant to be browser-compatible. The help offers two outs: use a browser-compatible alternative, or add the module to the `allow` list when Node usage is intentional (e.g. SSR-only or build-time code).

Source

Thrown at crates/oxc_linter/src/rules/import/no_nodejs_modules.rs:21

    AstKind,
    ast::{Expression, TSModuleReference},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_str::CompactStr;
use rustc_hash::FxHashSet;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
};

fn no_nodejs_modules_diagnostic(span: Span, module_name: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Do not import Node.js builtin module `{module_name}`"))
        .with_help("Use a browser-compatible alternative or add this module to the `allow` list if Node.js usage is intentional.")
        .with_label(span)
}

#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
#[schemars(rename_all = "camelCase", deny_unknown_fields)]
pub struct NoNodejsModulesConfig {
    /// Array of names of allowed modules. Defaults to an empty array.
    allow: FxHashSet<CompactStr>,
}

#[derive(Debug, Default, Clone, Deserialize, Serialize, JsonSchema)]
pub struct NoNodejsModules(Box<NoNodejsModulesConfig>);

impl std::ops::Deref for NoNodejsModules {
    type Target = NoNodejsModulesConfig;

    fn deref(&self) -> &Self::Target {

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Swap to a browser-compatible alternative (e.g. node:path URL handling, Web Crypto instead of node:crypto, whatwg URL instead of node:url)
  2. Split platform code: move the Node dependency behind a server-only module and import that instead
  3. Add intentional exceptions to the allow list: `{ "allow": ["node:path", "node:fs"] }` for files that genuinely run on Node
  4. Scope the rule to browser/shared directories via config overrides and leave server directories unchecked

Example fix

// before
import path from 'node:path';
const img = path.join(assetsDir, 'logo.png');

// after
const img = new URL('./logo.png', import.meta.url).href;
Defensive patterns

Strategy: validation

Validate before calling

// .oxlintrc.json
{ "rules": { "import/no-nodejs-modules": ["warn", { "allow": ["node:path"] }] } }
// browser-side pre-check: rg -n "from\\s+['\"](node:)?(fs|path|crypto|util|os|child_process)['\"]" src/client

Prevention

When it happens

Trigger: An import whose bare specifier names a Node builtin (with or without the `node:` prefix) and is not in the configured `allow` set — reported from no_nodejs_modules_diagnostic at crates/oxc_linter/src/rules/import/no_nodejs_modules.rs:21. Typical: `import fs from 'fs'`, `import path from 'node:path'`, `import { promisify } from 'util'` in shared/browser code.

Common situations: Isomorphic packages where a server util leaked into client-shared code; pulling a small helper from a Node script into app code; SSR frameworks (Next.js) where some files run only server-side but the rule applies repo-wide.

Related errors


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