oxc-project/oxc · warning · OxcDiagnostic
Expected throw instead of Promise.reject
Error message
Expected throw instead of Promise.reject
What it means
Diagnostic from the oxlint rule `promise/no-return-wrap` (plugin `promise`) for the Reject variant. It flags `return Promise.reject(e)` inside a promise handler. The idiomatic equivalent is `throw e`: throwing propagates through the chain to the next `catch` with better stack information in some engines, while a returned rejected promise is a second-class way to signal failure from a handler. Setting `{ "allowReject": true }` in the rule config makes returning `Promise.reject` legal (the rule's doc comment documents exactly this escape hatch).
Source
Thrown at crates/oxc_linter/src/rules/promise/no_return_wrap.rs:32
use oxc_ast_visit::VisitJs;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use schemars::JsonSchema;
use serde::Deserialize;
fn no_return_wrap_diagnostic(span: Span, issue: &ReturnWrapper) -> OxcDiagnostic {
let warn_msg = match issue {
ReturnWrapper::Resolve => "Avoid wrapping return values in Promise.resolve",
ReturnWrapper::Reject => "Expected throw instead of Promise.reject",
};
let help_msg = match issue {
ReturnWrapper::Resolve => "Return the value being passed into Promise.resolve instead",
ReturnWrapper::Reject => "Throw the value being passed into Promise.reject instead",
};
OxcDiagnostic::warn(warn_msg).with_help(help_msg).with_label(span)
}
#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoReturnWrap {
/// `allowReject` allows returning `Promise.reject` inside a promise handler.
///
/// With `allowReject` set to `true` the following are examples of correct code:
///
/// ```js
/// myPromise().then(
/// function() {
/// return Promise.reject(0)
/// })
/// ```
///
/// ```js
/// myPromise().then().catch(() => Promise.reject("err"))View on GitHub (pinned to e1e7af627c)
Solutions
- Replace with `throw`: `throw new Error(...)` inside the handler
- If the team convention is returning `Promise.reject`, set `{ "allowReject": true }` in the rule configuration
- Rethrow the original error with context: `throw new Error('context', { cause: err })`
Example fix
// before
promise.catch(err => {
return Promise.reject(new Error('wrapped: ' + err.message))
})
// after
promise.catch(err => {
throw new Error('wrapped: ' + err.message)
}) Defensive patterns
Strategy: validation
Validate before calling
npx oxlint --promise/no-return-wrap src/
# team convention prefers returning Promise.reject? permit it:
# { "rules": { "promise/no-return-wrap": ["error", { "allowReject": true }] } } Prevention
- Signal failure from handlers with `throw`, reserve `return` for values
- If the codebase standardizes on `return Promise.reject`, set `allowReject: true` once in shared config
- Rethrow with context (`new Error('ctx', { cause: err })`) instead of wrapping via Promise.reject
When it happens
Trigger: `promise.catch(err => { return Promise.reject(new Error('wrapped')) })`; `then(val => { if (!val) return Promise.reject(new Error('missing')) })` with default `allowReject: false`.
Common situations: Error-mapping code inside `catch` handlers; guard clauses written before the team standardized on `throw`; codebases that deliberately prefer `Promise.reject` and need the `allowReject` config.
Related errors
- Prefer `catch` to `then(a, b)` or `then(null, b)`
- Promise executor functions should not be `async`.
- Unexpected `await` inside a loop.
- Avoid nesting promises.
- Do not use `new` on `Promise.{static_name}`
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/5eea39390214378c.
Report an issue: GitHub.