{"record":{"id":"17c7d58475183211","repo":"oxc-project/oxc","slug":"unexpected-access-to-module-exports","errorCode":null,"errorMessage":"Unexpected access to `module.exports`.","messagePattern":"Unexpected access to `module\\.exports`\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"info","filePath":"crates/oxc_linter/src/rules/node/exports_style.rs","lineNumber":27,"sourceCode":"use schemars::JsonSchema;\nuse serde::{Deserialize, Serialize};\n\nuse crate::{\n    ast_util::iter_outer_expressions,\n    config::GlobalValue,\n    context::LintContext,\n    rule::{Rule, TupleRuleConfig},\n    utils::{is_global_exports_assignment_target, is_global_module_exports},\n};\n\nfn unexpected_exports_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected access to `exports`.\")\n        .with_help(\"Use `module.exports` instead.\")\n        .with_label(span)\n}\n\nfn unexpected_module_exports_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected access to `module.exports`.\")\n        .with_help(\"Use `exports` instead.\")\n        .with_label(span)\n}\n\nfn unexpected_assignment_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected assignment to `exports`.\")\n        .with_help(\"Do not modify `exports` itself.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, JsonSchema)]\n#[serde(rename_all = \"kebab-case\")]\nenum ExportsStyleMode {\n    #[default]\n    #[serde(rename = \"module.exports\")]\n    /// Requires `module.exports` and disallows `exports`\n    ModuleExports,\n    /// Requires `exports` and disallows `module.exports`","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/node/exports_style.rs#L9-L45","documentation":"Diagnostic from oxlint rule node/exports-style (style category), the mirror of its sibling: when the rule is configured in 'exports' mode, the codebase standardizes on the short `exports` alias, and any reference to `module.exports` is flagged with the suggestion to use `exports`. Same rationale — one idiom per codebase — and same caveat: only safe because the other diagnostic in this rule forbids reassigning `exports` itself.","triggerScenarios":"Config \"node/exports-style\": [\"error\", \"exports\"] (the ExportsStyleMode::Exports serde rename) and the source references the global `module.exports` — e.g. module.exports.foo = 42; — resolved through the same is_global_module_exports helper used for the sibling diagnostics.","commonSituations":"Codebases that adopted the shorter exports style (common in older Node libs) now linted with oxlint; mode flipped in shared config while some files still use the long form; migrations from eslint-plugin-n/exports-style with the same option value.","solutions":["Rewrite the access: 'module.exports.foo = 42' becomes 'exports.foo = 42'","If the file must use module.exports (e.g. it reassigns the export target), keep it and scope the rule to mode \"module.exports\" for that directory, or disable inline","Normalize the whole module to one form so both diagnostics stay silent"],"exampleFix":"// before (mode: exports)\nmodule.exports.hello = function () {};\n\n// after\nexports.hello = function () {};","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n\"rules\": { \"node/exports-style\": [\"error\", \"exports\"] }\n\nnpx oxlint -c .oxlintrc.json --deny-warning .","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When standardizing on the exports alias, always keep node/no-exports-assign on — the short form is only safe while `exports` itself is never rebound","Encode the chosen idiom in the shared config, not per-file pragmas, so drift is visible in review","Codemod existing module.exports.x to exports.x in one commit before enabling"],"tags":["node","commonjs","exports","style","oxlint"],"backgroundTag":"commonjs-exports-style","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}