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
- Swap to a browser-compatible alternative (e.g. node:path URL handling, Web Crypto instead of node:crypto, whatwg URL instead of node:url)
- Split platform code: move the Node dependency behind a server-only module and import that instead
- Add intentional exceptions to the allow list: `{ "allow": ["node:path", "node:fs"] }` for files that genuinely run on Node
- 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
- Keep server-only code in a separate directory and exclude it from this rule
- Prefer Web-platform APIs (URL, Web Crypto, fetch) in shared code
- When adding a Node builtin to shared utils, add it to the allow list consciously in the same commit
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
- Could not find the reuseWorker option in ${path}
- Do not assign to imported bindings
- Expected '{curr_kind}' syntax before '{prev_kind}' syntax.
- Imports should be sorted alphabetically.
- Member '{name}' of the import declaration should be sorted a
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/292614dfabbc1b56.
Report an issue: GitHub.