{"record":{"id":"4b38b2f5d3df7e06","repo":"oxc-project/oxc","slug":"invalid-character-comparison","errorCode":null,"errorMessage":"Invalid character comparison","messagePattern":"Invalid character comparison","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/oxc/bad_char_at_comparison.rs","lineNumber":19,"sourceCode":"use oxc_ast::{\n    AstKind,\n    ast::{BinaryExpression, Expression, TSType, VariableDeclarator},\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\n\nuse crate::{\n    AstNode, ast_util::is_method_call, ast_util::variable_declaration_kind, context::LintContext,\n    rule::Rule,\n};\n\nfn bad_char_at_comparison_diagnostic(\n    character_access: Span,\n    compared_string: Span,\n    len: usize,\n) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Invalid character comparison\")\n        .with_help(\"Character access returns a string of length at most 1. If the return value is compared with a string of length greater than 1, the comparison will always be false.\")\n        .with_labels([\n            character_access.label(\"A single character is accessed here\"),\n            compared_string.label(format!(\"And compared with a string of length {len} here\")),\n        ])\n}\n\n#[derive(Debug, Default, Clone)]\npub struct BadCharAtComparison;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// This rule warns when a character accessed with `charAt`, `at`, or bracket notation is\n    /// compared with a string of length greater than 1.\n    ///\n    /// ### Why is this bad?\n    ///","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/oxc/bad_char_at_comparison.rs#L1-L37","documentation":"Diagnostic from oxlint rule oxc/bad-char-at-comparison (correctness category). Character access — str.charAt(i), str[i] — returns a string of length at most 1 (or ''), so comparing that result for equality with a string literal longer than one character is provably always false; the guarded branch is dead code that never runs and never fails loudly. The diagnostic carries two labels: where the single character is accessed, and where it is compared against a literal of the stated length.","triggerScenarios":"An equality comparison between a character-access expression (charAt / bracket indexing on a string) and a string literal whose length is greater than 1 — the diagnostic formats that length into the second label. Canonical trigger: if (name.charAt(0) === 'Dr') { ... } — the condition can never be true, so the block is unreachable.","commonSituations":"Prefix/suffix checks on titles ('Dr', 'Sir'), currency symbols, mime types, or file extensions written as equality by developers porting instincts from languages where single-char and string comparisons unify; code that passes tests written against the same wrong assumption — the branch silently never executes.","solutions":["Use startsWith/endsWith for prefix/suffix intent: name.startsWith('Dr')","Compare against the single character actually accessed: name.charAt(0) === 'D'","For substring containment use includes() or slice() comparisons instead of char access"],"exampleFix":"// before\nif (mimeType.charAt(0) === 'im') { // always false: charAt returns 1 char\n  renderImage();\n}\n\n// after\nif (mimeType.startsWith('im')) {\n  renderImage();\n}","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n\"rules\": { \"oxc/bad-char-at-comparison\": \"error\" }\n\nnpx oxlint -c .oxlintrc.json --deny-warning .","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use startsWith/endsWith for any prefix/suffix check instead of indexing single characters","When reviewing charAt/[0] comparisons, eyeball the literal's length — more than one character means dead code","Cover flagged branches with tests; always-false conditions hide as silently skipped code that tests written by the same author also skip"],"tags":["oxc","javascript","string","comparison","logic-bug","dead-code","oxlint"],"backgroundTag":"always-false-string-comparison","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}