oxc-project/oxc · error · OxcDiagnostic
Expected an error object to be thrown
Error message
Expected an error object to be thrown
What it means
`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.
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_throw_literal.rs:12
use oxc_ast::{AstKind, ast::Expression};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use crate::{AstNode, ast_util::could_be_error, context::LintContext, rule::Rule};
fn no_throw_literal_diagnostic(span: Span, is_undef: bool) -> OxcDiagnostic {
let message =
if is_undef { "Do not throw undefined" } else { "Expected an error object to be thrown" };
OxcDiagnostic::warn(message)
.with_help("Throwing literals or non-Error objects is not recommended. Use an Error object instead.")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoThrowLiteral;
declare_oxc_lint!(
/// ### What it does
///
/// Disallows throwing literals or non-Error objects as exceptions.
///
/// ::: warning
/// 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).
/// The typescript rule is more reliable than the Javascript version, as it has less false positive, and can catch more cases.
/// :::
///
/// ### Why is this bad?View on GitHub (pinned to e1e7af627c)
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.
Example fix
// before
function load(id) {
if (!id) throw 'missing id';
}
// after
function load(id) {
if (!id) throw new Error('missing id');
} Defensive patterns
Strategy: type-guard
Validate before calling
// guard the value before throwing
function toError(value: unknown): Error {
return value instanceof Error ? value : new Error(String(value));
} Type guard
function isError(value: unknown): value is Error {
return value instanceof Error;
} Try / catch
try {
risky();
} catch (e) {
throw e instanceof Error ? e : new Error(String(e)); // normalize at boundaries
} Prevention
- 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.
When it happens
Trigger: `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.
Common situations: 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`.
Related errors
- Do not throw undefined
- Empty array binding pattern
- Empty object binding pattern
- Expected method{method_name_str} to have this.
- {name} has a complexity of {complexity}. Maximum allowed is
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/9ef638ecc7ba6a6b.
Report an issue: GitHub.