oxc-project/oxc · error

Variable or `function` declarations are not allowed in neste

Error message

Variable or `function` declarations are not allowed in nested blocks

What it means

Diagnostic from oxlint's no-inner-declarations rule (ESLint port, eslint:recommended). Function declarations inside nested blocks have implementation-defined hoisting in sloppy mode, and var inside blocks hoists to the function root while looking block-scoped. The rule reports function declarations (default 'functions' mode) or functions plus var (option 'both') declared anywhere except the program root or the top level of a function body, with help text 'Move {decl_type} declaration to {body} root'.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_inner_declarations.rs:11

use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

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

fn no_inner_declarations_diagnostic(decl_type: &str, body: &str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Variable or `function` declarations are not allowed in nested blocks")
        .with_help(format!("Move {decl_type} declaration to {body} root"))
        .with_label(span)
}

/// Determines what type of declarations to check.
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
enum NoInnerDeclarationsConfig {
    /// Disallows function declarations in nested blocks.
    #[default]
    Functions,
    /// Disallows function and var declarations in nested blocks.
    Both,
}

#[derive(Debug, Default, Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
struct NoInnerDeclarationsOptions {

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Move the function declaration to the top of the enclosing function or program.
  2. Replace it with a function expression or arrow function assigned to const inside the block.
  3. Keep the rule in default 'functions' mode, or switch to 'both' only after fixing var-in-block findings.
  4. Extract the block body into a named function so the declaration lands at a valid root.

Example fix

// before
if (enabled) {
  function run() {
    start();
  }
  run();
}

// after
function run() {
  start();
}
if (enabled) {
  run();
}
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint -A all -D no-inner-declarations src/

Prevention

When it happens

Trigger: if (x) { function handle() {} } in a script; for (...) { var item = ...; } with the 'both' option; function declarations inside plain blocks or switch cases; declarations in catch blocks.

Common situations: Sloppy-mode scripts where block-level function declarations behave differently across engines; var-in-loop refactors; enabling the 'both' option on an older codebase and hitting hundreds of var reports.

Related errors


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