oxc-project/oxc · warning · OxcDiagnostic
'{name}' was used before it was defined.
Error message
'{name}' was used before it was defined. What it means
Diagnostic from oxlint's no-use-before-define rule. An identifier is referenced at a point where its declaration has not been reached in source order; for let/const/class/enum bindings this is a runtime TDZ ReferenceError, for hoisted var/function it merely hurts readability. Config flags control which kinds are checked (defaults: classes, enums, functions, typedefs, variables all true; ignoreTypeReferences true; allowNamedExports false).
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_use_before_define.rs:27
reference::Reference,
scope::ScopeId,
symbol::{SymbolFlags, SymbolId},
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
AstNode,
context::LintContext,
rule::{DefaultRuleConfig, Rule},
};
fn no_use_before_define_diagnostic(
name: &str,
usage_span: Span,
declaration_span: Option<Span>,
) -> OxcDiagnostic {
let diagnostic = OxcDiagnostic::warn(format!("'{name}' was used before it was defined."))
.with_label(usage_span.primary_label("used here"))
.with_help("Move the declaration before any references to it, or remove the reference if it is not needed.");
if let Some(declaration_span) = declaration_span.filter(|span| !span.is_unspanned()) {
diagnostic.and_label(declaration_span.label("defined here"))
} else {
diagnostic
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoUseBeforeDefineConfig {
/// Allow named exports that appear before declaration.
allow_named_exports: bool,
/// Check class declarations.
classes: bool,
/// Check enum declarations.
enums: bool,View on GitHub (pinned to a3d33dda7c)
Solutions
- Move the declaration above the first use.
- Convert const fn = () => {} to a hoisted function fn() {} when early calls are intended.
- Relax specific kinds in .oxlintrc.json, e.g. { "functions": false } (same for classes/variables/enums/typedefs).
- For type-only forward references, keep "ignoreTypeReferences": true (default) instead of disabling the rule.
Example fix
// before const main = () => helper(); const helper = () => 1; // after const helper = () => 1; const main = () => helper();
Defensive patterns
Strategy: validation
Prevention
- Declare before use, especially for const, class, and enum bindings (TDZ crashes at runtime otherwise).
- Use function declarations when calls must precede definitions.
- Tune the rule's functions/classes/variables/enums/typedefs flags to your team's style once, in .oxlintrc.json, instead of per-file disables.
- Keep "ignoreTypeReferences": true (default) so legitimate forward type references do not fire.
When it happens
Trigger: Calling a const arrow function before its declaration; new Foo() above class Foo {}; referencing an enum member before the enum; using a variable declared with let later in the same scope.
Common situations: Mutually recursive helpers written bottom-up; hoisting-reliant code migrated to const arrow functions; circular imports; named exports referenced before declaration in module scope.
Related errors
- Variable or `function` declarations are not allowed in neste
- 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@a3d33dda7c (2026-08-20).
Data as JSON: /api/errors/b67d248d9ccb5c0a.
Report an issue: GitHub.