oxc-project/oxc · warning

Unexpected assignment to read-only global variable.

Error message

Unexpected assignment to read-only global variable.

What it means

The read-only variant inside oxlint's no-implicit-globals rule: writing to a global that the lint config (or well-known built-ins) marks read-only, such as undefined, NaN, Infinity, or environment globals declared readonly. In strict mode such writes throw a TypeError at runtime; in sloppy mode they silently no-op, so the rule reports them statically.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_implicit_globals.rs:37

            "Wrap it in an IIFE for a local variable, or assign it as a global property for a global variable.",
        )
        .with_label(span)
}

fn global_lexical_binding_diagnostic(kind: &'static str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Unexpected {kind} declaration in the global scope."))
        .with_help("Wrap it in a block or in an IIFE.")
        .with_label(span)
}

fn global_variable_leak_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Global variable leak.")
        .with_help("Declare the variable if it is intended to be local.")
        .with_label(span)
}

fn assignment_to_readonly_global_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Unexpected assignment to read-only global variable.").with_label(span)
}

fn redeclaration_of_readonly_global_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Unexpected redeclaration of read-only global variable.").with_label(span)
}

#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
struct NoImplicitGlobalsConfig {
    lexical_bindings: bool,
}

#[derive(Debug, Default, Clone, Deserialize, Serialize, JsonSchema)]
pub struct NoImplicitGlobals(NoImplicitGlobalsConfig);

declare_oxc_lint!(
    /// ### What it does
    ///

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Use a new local variable instead of writing to the global.
  2. Mark the global writable in the globals config if assignment is legitimate (e.g. dedicated polyfill files).
  3. Delete pre-ES5 undefined guards.

Example fix

// before
undefined = 'fallback';

// after
const fallback = 'fallback';
Defensive patterns

Strategy: validation

Validate before calling

const readonlyWrite = /\b(?:undefined|NaN|Infinity)\s*=[^=]/.test(source);

Prevention

When it happens

Trigger: undefined = fallback;; assigning to a global listed as readonly in the globals section of .oxlintrc.json; polyfill code overwriting readonly names in the same lint pass as application code.

Common situations: Old defensive-undefined assignments; shared configs marking environment globals readonly; polyfill files linted with the app's strict settings.

Related errors


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