{"record":{"id":"2ac1a6f700cd4622","repo":"oxc-project/oxc","slug":"the-update-clause-in-this-loop-moves-the-variable","errorCode":null,"errorMessage":"The update clause in this loop moves the variable in the wrong direction","messagePattern":"The update clause in this loop moves the variable in the wrong direction","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/eslint/for_direction.rs","lineNumber":20,"sourceCode":"    AstKind,\n    ast::{\n        AssignmentExpression, AssignmentTarget, Expression, IdentifierReference,\n        SimpleAssignmentTarget,\n    },\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\nuse oxc_syntax::{\n    operator::BinaryOperator::{GreaterEqualThan, GreaterThan, LessEqualThan, LessThan},\n    operator::{AssignmentOperator, BinaryOperator, UnaryOperator, UpdateOperator},\n};\n\nuse crate::fixer::{RuleFix, RuleFixer};\nuse crate::{AstNode, context::LintContext, rule::Rule};\n\nfn for_direction_diagnostic(test_span: Span, update_span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"The update clause in this loop moves the variable in the wrong direction\")\n        .with_help(\"Use `while` loop for intended infinite loop\")\n        .with_labels([\n            test_span.label(\"This test moves in the wrong direction\"),\n            update_span.label(\"with this update\"),\n        ])\n}\n\n#[derive(Debug, Default, Clone)]\npub struct ForDirection;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallow `for` loops where the update clause moves the counter in the wrong\n    /// direction, preventing the loop from reaching its stop condition.\n    ///\n    /// ### Why is this bad?\n    ///","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/for_direction.rs#L2-L38","documentation":"Oxlint's port of the ESLint rule for-direction (crates/oxc_linter/src/rules/eslint/for_direction.rs:19). It compares the direction implied by the loop test with the effect of the update clause: when the update moves the counter away from satisfying the test (test `i < n` with `i--`, or `i > n` with `i++`, including `+=`/`-=` of the wrong sign), the loop either never runs or never terminates. Two labels tie the test ('This test moves in the wrong direction') to the update ('with this update'), and the help suggests a `while` loop for intentional infinite loops.","triggerScenarios":"`for (let i = 0; i < 10; i--) {}`, `for (let j = n; j > 0; j++) {}`, or assignment updates like `i -= 1` against an upper-bound test.","commonSituations":"Flipping iteration direction while editing a loop; copy-pasting a countdown loop and changing only the condition; signed step values that go negative against a `<` test.","solutions":["Fix the update so it moves toward the test boundary (`i++` with `i < n`, `i--` with `i > n`).","If the infinite loop is intentional, write `while (true)` with a `break` so the intent is explicit.","Re-check the test operator — sometimes the update is correct and the condition was inverted."],"exampleFix":"// before (never terminates)\nfor (let i = 0; i < items.length; i--) {\n  handle(items[i]);\n}\n\n// after\nfor (let i = 0; i < items.length; i++) {\n  handle(items[i]);\n}","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n{\n  \"rules\": {\n    \"for-direction\": \"error\"\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When editing a loop, re-check test and update together — they must move toward each other.","Use `while (true)` + `break` for intentional infinite loops so linters and readers see intent.","Keep counters signed one way; avoid `i += step` where step can flip sign against a fixed test."],"tags":["eslint","oxlint","for-loop","infinite-loop","bug"],"backgroundTag":"infinite-for-loop","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}