{"record":{"id":"9ef638ecc7ba6a6b","repo":"oxc-project/oxc","slug":"expected-an-error-object-to-be-thrown","errorCode":null,"errorMessage":"Expected an error object to be thrown","messagePattern":"Expected an error object to be thrown","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/eslint/no_throw_literal.rs","lineNumber":12,"sourceCode":"use oxc_ast::{AstKind, ast::Expression};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\n\nuse crate::{AstNode, ast_util::could_be_error, context::LintContext, rule::Rule};\n\nfn no_throw_literal_diagnostic(span: Span, is_undef: bool) -> OxcDiagnostic {\n    let message =\n        if is_undef { \"Do not throw undefined\" } else { \"Expected an error object to be thrown\" };\n\n    OxcDiagnostic::warn(message)\n        .with_help(\"Throwing literals or non-Error objects is not recommended. Use an Error object instead.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoThrowLiteral;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallows throwing literals or non-Error objects as exceptions.\n    ///\n    /// ::: warning\n    /// This rule has been deprecated, please instead use [typescript/only-throw-error](https://oxc.rs/docs/guide/usage/linter/rules/typescript/only-throw-error.html).\n    /// The typescript rule is more reliable than the Javascript version, as it has less false positive, and can catch more cases.\n    /// :::\n    ///\n    /// ### Why is this bad?","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_throw_literal.rs#L1-L30","documentation":"`no-throw-literal` reports `throw` statements whose operand is a literal or non-Error value — strings, numbers, booleans, objects, arrays, `null`. Only the `is_undef` case gets the separate \"Do not throw undefined\" message; this is the general variant. Non-Error throws lose the stack trace and `message`/`name` structure that catch sites and error reporters (Sentry, unhandledRejection handlers) expect, and they crash `catch (e) { e.message }` code.","triggerScenarios":"`throw 'not found';`, `throw 404;`, `throw { code: 'X' };` — any ThrowStatement whose expression is not an Error construction; the helper `could_be_error` filters values that can be statically proven to be Errors.","commonSituations":"Older codebases predating Error-as-convention; throwing plain response/error codes in API layers; refactoring promise chains where `reject('timeout')` style strings migrate into `throw`.","solutions":["Wrap the value in an Error: `throw new Error('not found');`.","For typed errors, subclass Error and set `name`, or use a cause: `throw new Error('wrap', { cause: original })`.","Search the codebase for existing literals: `rg \"throw\\\\s+['\\\"0-9{]\" src/` and fix each."],"exampleFix":"// before\nfunction load(id) {\n  if (!id) throw 'missing id';\n}\n\n// after\nfunction load(id) {\n  if (!id) throw new Error('missing id');\n}","handlingStrategy":"type-guard","validationCode":"// guard the value before throwing\nfunction toError(value: unknown): Error {\n  return value instanceof Error ? value : new Error(String(value));\n}","typeGuard":"function isError(value: unknown): value is Error {\n  return value instanceof Error;\n}","tryCatchPattern":"try {\n  risky();\n} catch (e) {\n  throw e instanceof Error ? e : new Error(String(e)); // normalize at boundaries\n}","preventionTips":["Always `throw new Error(...)` (or a subclass) — never primitives or plain objects.","Wrap top-level handlers so non-Error throws are normalized before logging/reporting.","Search for `throw '` and `throw {` patterns during review."],"tags":["eslint","oxlint","no-throw-literal","errors","throw","exceptions"],"backgroundTag":"throwing-non-error","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"}