oxc-project/oxc · error · OxcDiagnostic
Math.min and Math.max combination leads to constant result
Error message
Math.min and Math.max combination leads to constant result
What it means
Oxlint rule `oxc/bad-min-max-func` detects a clamp expression `Math.min(Math.max(x, a), b)` (or the mirrored `Math.max(a, Math.min(0, x))`) where the constant bounds are ordered so the whole expression collapses to a constant. The implementation folds the numeric-literal arguments of each `Math.min`/`Math.max` call and reports the constant result (e.g. `Math.min(Math.max(100, x), 0)` always evaluates to 0). It is a correctness bug: the clamp silently returns a fixed number instead of clamping.
Source
Thrown at crates/oxc_linter/src/rules/oxc/bad_min_max_func.rs:12
use oxc_ast::{
AstKind,
ast::{Argument, CallExpression, Expression},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{AstNode, context::LintContext, rule::Rule};
fn bad_min_max_func_diagnostic(constant_result: f64, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Math.min and Math.max combination leads to constant result")
.with_help(format!(
"This evaluates to {constant_result:?} because of the incorrect `Math.min`/`Math.max` combination"
))
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct BadMinMaxFunc;
declare_oxc_lint!(
/// ### What it does
///
/// Checks whether the clamp function `Math.min(Math.max(x, y), z)` always evaluates to a
/// constant result because the arguments are in the wrong order.
///
/// ### Why is this bad?
///
/// The `Math.min(Math.max(x, y), z)` function is used to clamp a value between two other values.View on GitHub (pinned to e1e7af627c)
Solutions
- Reorder so the lower bound goes in `Math.max` and the upper bound in `Math.min`: `Math.min(100, Math.max(0, x))`
- Double-check which of the two constants is smaller before nesting the calls
- Extract a `clamp(x, lo, hi)` helper so the argument order is encoded once and unit-tested
- Keep `oxc/bad-min-max-func` (correctness) enabled in CI
Example fix
// before const clamped = Math.min(Math.max(100, x), 0); // always 0 // after const clamped = Math.min(100, Math.max(0, x));
Defensive patterns
Strategy: validation
Validate before calling
// .oxlintrc.json — fail CI on this bug class
{
"rules": { "oxc/bad-min-max-func": "error" }
}
// CLI: npx oxlint src/ Prevention
- Memorize the canonical clamp shape: Math.min(HI, Math.max(LO, x))
- Unit-test clamp helpers with inputs below LO, inside, and above HI — a collapsed constant fails all three
- Centralize clamping in one helper so the argument order is verified once
When it happens
Trigger: `Math.min(Math.max(100, x), 0)` -> always 0; `Math.max(1000, Math.min(0, z))` -> always 1000; bounds spread across extra numeric args like `Math.min(Math.max(1000, x), 100, 3)` -> always 3; also computed access such as `Math["min"](0, Math.max(100, x))`.
Common situations: Writing clamp/normalize helpers (RGB 0-255, percent 0-100) and swapping which bound goes to min vs max; copy-pasting a clamp snippet and editing the bounds; refactoring `Math.max(0, Math.min(100, x))` into the wrong nesting order.
Related errors
- Invalid character comparison
- Bad comparison sequence
- Unexpected object literal comparison.
- Unexpected array literal comparison.
- Left-hand side of `&&` operator has no effect.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/af2a53226d888110.
Report an issue: GitHub.