{"record":{"id":"95469da428d9a70f","repo":"oxc-project/oxc","slug":"do-not-assign-to-the-exception-parameter","errorCode":null,"errorMessage":"Do not assign to the exception parameter.","messagePattern":"Do not assign to the exception parameter\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/no_ex_assign.rs","lineNumber":11,"sourceCode":"use oxc_ast::AstKind;\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_ecmascript::BoundNames;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_semantic::AstNode;\nuse oxc_span::Span;\n\nuse crate::{context::LintContext, rule::Rule};\n\nfn no_ex_assign_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Do not assign to the exception parameter.\")\n        .with_help(\"Remove the assignment to the exception parameter, or refactor the code to use a different variable.\")\n        .with_note(\"If code in a catch block assigns a value to the exception parameter, it becomes impossible to refer to the error. Since there is no alternative way to access to this data, assignment of the parameter is absolutely destructive.\")\n        .with_label(span.label(\"this assignment destroys access to the caught exception\"))\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoExAssign;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallow reassigning exceptions in catch clauses.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// If a catch clause in a try statement accidentally\n    /// (or purposely) assigns another value to the exception parameter,\n    /// it is impossible to refer to the error from that point on.","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_ex_assign.rs#L1-L29","documentation":"This diagnostic comes from the `no_ex_assign` rule in oxlint. It reports an assignment to the exception parameter of a `catch` block. After the assignment, the original error object is lost, and no other path leads to it. The rule collects the bound names of the catch parameter with `BoundNames`, so destructured names count too, and reports writes to them.","triggerScenarios":"Inside a catch block: `catch (e) { e = new Error('wrapped'); }`, the destructured form `catch ({ message }) { message = 'x'; }`, or a compound write such as `e += info`. The report labels the assignment span.","commonSituations":"A developer tries to normalize or wrap the caught error in place. Old patterns reuse the catch variable as a scratch variable. A rename refactor makes the catch parameter collide with a nearby name by habit.","solutions":["Use a new variable: `const wrapped = new Error('context'); wrapped.cause = e;`.","Rethrow with cause: `throw new Error('context', { cause: e });`.","Suppress only when the value is provably unused after the write: `// oxlint-disable-next-line no-ex-assign`."],"exampleFix":"// before\ntry {\n  parse(raw);\n} catch (e) {\n  e = new Error('parse failed');\n  throw e;\n}\n\n// after\ntry {\n  parse(raw);\n} catch (e) {\n  throw new Error('parse failed', { cause: e });\n}","handlingStrategy":"validation","validationCode":"// warn on writes to a catch parameter (simple text heuristic)\nif (/catch\\s*\\(\\s*(?:[A-Za-z_$][\\w$]*|\\{[^}]*\\})\\s*\\)[\\s\\S]{0,120}?\\b[A-Za-z_$][\\w$]*\\s*=(?!=)/.test(src)) {\n  console.warn('possible assignment to catch parameter');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat the catch parameter as read-only.","Wrap errors with a `cause` chain; never overwrite the original.","Destructure only the fields you read, never write to them."],"tags":["javascript","eslint","lint","error-handling","catch"],"backgroundTag":"lint-catch-parameter-reassignment","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"}