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
- Move the function declaration to the top of the enclosing function or program.
- Replace it with a function expression or arrow function assigned to const inside the block.
- Keep the rule in default 'functions' mode, or switch to 'both' only after fixing var-in-block findings.
- 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
- Declare functions at the top level of the enclosing function or program.
- Use const arrow or function expressions for block-local helpers.
- Adopt the 'both' option only after fixing var-in-block findings.
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
- '{name}' is a function.
- All 'var' declarations must be at the top of the function sc
- TS5042
- Empty array binding pattern
- Empty object binding pattern
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/08a0a00ede8c49c1.
Report an issue: GitHub.