oxc-project/oxc · warning · OxcDiagnostic
Avoid wrapping return values in Promise.resolve
Error message
Avoid wrapping return values in Promise.resolve
What it means
Diagnostic from the oxlint rule `promise/no-return-wrap` (plugin `promise`) for the Resolve variant. It flags `return Promise.resolve(x)` inside a promise handler (then/catch callback). Returning a value from a handler already wraps it: the chain assimilates thenables automatically, so the explicit `Promise.resolve` wrapper adds an extra microtask tick and visual noise for no behavior change. The rule has an `allowReject` option, but it only affects the reject variant, not this one.
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
- Return the value (or the thenable) directly: `return transform(val)`
- If the value may be a promise, still return it directly - the chain flattens it
- For conditionally-async work, return the promise from an async handler declared `async val => ...`
Example fix
// before
promise.then(val => {
return Promise.resolve(transform(val))
})
// after
promise.then(val => {
return transform(val)
}) Defensive patterns
Strategy: validation
Validate before calling
npx oxlint --promise/no-return-wrap src/
Prevention
- Remember handlers auto-wrap: any returned value or thenable is assimilated
- Grep for `return Promise.resolve(` inside `.then(`/`.catch(` callbacks during cleanup sprints
- Reserve `Promise.resolve(...)` for starting chains or flattifying thenables, not for return values
When it happens
Trigger: `promise.then(val => { return Promise.resolve(transform(val)) })`; returning `Promise.resolve(...)` from any `.then()`/`.catch()` handler.
Common situations: Authors unsure whether handlers auto-wrap return values; refactors out of `new Promise` wrappers that leave `Promise.resolve` behind; defensive wrapping of possibly-thenable values.
Related errors
- Avoid nesting promises.
- Don't return in a finally callback
- Prefer await to then()/catch()/finally()
- Promise executor functions should not be `async`.
- Unexpected `await` inside a loop.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/137df9e01f5f0c0e.
Report an issue: GitHub.