oxc-project/oxc · warning
Unexpected constant condition
Error message
Unexpected constant condition
What it means
Diagnostic from the oxlint rule `no-constant-condition` (crates/oxc_linter/src/rules/eslint/no_constant_condition.rs). It fires when the test of an `if`, ternary, `while`, `do-while`, or `for` is a constant expression (literal, constant arithmetic, always-truthy object, `x ||= true`, etc.), labeled 'this expression will always evaluate to the same value'. Loop tests are governed by the `checkLoops` option: default `allExceptWhileTrue` keeps plain `while (true)` legal; `all`/`true` reports it; `none`/`false` skips loop tests entirely (with extra generator/yield-aware handling for loops that yield).
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_constant_condition.rs:22
use oxc_ast::{
AstKind,
ast::{ArrowFunctionExpression, Expression, Function, YieldExpression},
};
use oxc_ast_visit::VisitJs;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_syntax::{node::NodeId, scope::ScopeFlags};
use crate::{
AstNode,
ast_util::IsConstant,
context::LintContext,
rule::{DefaultRuleConfig, Rule},
};
fn no_constant_condition_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Unexpected constant condition")
.with_help("Update the condition to not be constant, or remove the condition entirely")
.with_label(span.label("this expression will always evaluate to the same value"))
}
#[derive(Debug, Default, Clone, PartialEq, JsonSchema, Serialize)]
#[serde(rename_all = "camelCase")]
enum CheckLoops {
All,
#[default]
AllExceptWhileTrue,
None,
}
impl<'de> Deserialize<'de> for CheckLoops {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{View on GitHub (pinned to e1e7af627c)
Solutions
- Replace the constant test with the real condition it was placeholder for.
- If the branch is dead, delete it (or gate it behind a named constant read from config so it is no longer statically constant).
- For intentional `while (true)` loops keep the default `checkLoops: "allExceptWhileTrue"`, or set it explicitly in .oxlintrc.json if your config was tightened to `all`.
- For deliberate constant tests (spec tests, benchmarks), suppress with `// oxlint-disable-next-line no-constant-condition`.
Example fix
// before
if (false) {
doSomethingUnfinished();
}
while (true) { poll(); }
// after
if (!featureEnabled) {
doSomethingUnfinished();
}
for (;;) { poll(); } // or keep checkLoops at "allExceptWhileTrue" Defensive patterns
Strategy: validation
Validate before calling
// Gate: constant tests in conditions (heuristic; rule handles folding) const constantTest = /\b(if|while)\s*\(\s*(true|false|null|undefined|\d+|['"][^'"]*['"])\s*\)/.test(src);
Prevention
- Wire real conditions before committing placeholders like if (false).
- Pin checkLoops to the value matching your loop style (default allExceptWhileTrue allows while(true)).
- Prefer for(;;) when you want an unconditional loop regardless of config.
When it happens
Trigger: `if (false) {...}`, `if (new Boolean(x)) {...}`, `x ? a : b` where x is a constant, `do {...} while (x = -1)`; plus `while (true)` only when checkLoops is `all`/`true`. Constants are computed with the shared IsConstant utility, so constant-foldable expressions and always-truthy boxed booleans count.
Common situations: Dead feature-flag branches left from `if (false)` debugging; placeholder conditions before wiring real inputs; infinite `while (true)` server loops tripping after someone sets `checkLoops: true`; ternaries over `typeof x === 'undefined'` styles that fold to constants.
Related errors
- Expected a conditional expression and instead saw an assignm
- Unexpected constant {lhs_name} on the left-hand side of a {e
- Unexpected constant binary expression
- Unexpected comparison to newly constructed object
- Unexpected comparison of two newly constructed objects
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/65d8a2b394cc4e6e.
Report an issue: GitHub.