oxc-project/oxc · warning · OxcDiagnostic

All 'var' declarations must be at the top of the function…

Error message

All 'var' declarations must be at the top of the function scope.

What it means

oxlint's `vars-on-top` rule enforces the style where every `var` declaration in a function (or program) scope precedes all other statements — matching what hoisting actually does at runtime. The diagnostic fires on any var declaration that follows a non-var statement in its scope; ambient TypeScript contexts are exempted via `has_ambient_typescript_ancestor`.

Solutions

  1. Replace var with let/const declared where the value is first needed (preferred modern fix)
  2. Or move the var declarations to the top of the function scope
  3. Disable or downgrade `vars-on-top` if the team has fully adopted let/const and the rule is pure noise

Example fix

// before
function process(input) {
  validate(input);
  var results = [];
  for (var item of input) results.push(transform(item));
  return results;
}

// after
function process(input) {
  validate(input);
  const results = [];
  for (const item of input) results.push(transform(item));
  return results;
}
Defensive patterns

Strategy: validation

Validate before calling

// .oxlintrc.json
{ "rules": { "vars-on-top": "warn" } }
// pre-commit: npx oxlint --fix src/legacy/

Prevention

When it happens

Trigger: `function f() { doFirst(); var x = 1; }` — a VariableDeclaration of kind var appearing after expression or other statements within the same function scope (or top-level program scope).

Common situations: Legacy ES5 codebases; incremental migrations where pockets of var remain; merge conflicts that move statements above existing var declarations.

Related errors


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

Appendix: source

Thrown at crates/oxc_linter/src/rules/eslint/vars_on_top.rs:10

use oxc_ast::AstKind;
use oxc_ast::ast::{Declaration, Expression, Program, Statement, VariableDeclarationKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

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

fn vars_on_top_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("All 'var' declarations must be at the top of the function scope.")
        .with_help("Consider moving this to the top of the functions scope or using let or const to declare this variable.")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct VarsOnTop;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Enforces that all `var` declarations are placed at the top of their containing scope.
    ///
    /// ### Why is this bad?
    ///
    /// In JavaScript, `var` declarations are hoisted to the top of their containing scope. Placing `var` declarations at the top explicitly improves code readability and maintainability by making the scope of variables clear.
    ///
    /// ### Examples
    ///

View on GitHub (pinned to e1e7af627c)