oxc-project/oxc · warning · OxcDiagnostic
Promise should not be resolved multiple times. Promise is po
Error message
Promise should not be resolved multiple times. Promise is potentially resolved on line {line}. What it means
Diagnostic from the oxlint rule `promise/no-multiple-resolved` (plugin `promise`, category `suspicious`). This is the flow-sensitive variant: the CFG analysis found that at least one (but not all) incoming path to the second `resolve`/`reject` call had already settled the promise, so the promise is 'potentially' already resolved on line N. The 'potentially' wording comes from the ResolvedKind::Potential classification in the rule's dominator-based path analysis. Such calls are no-ops when they are redundant, but indicate a missing guard, `else`, or early `return`.
Source
Thrown at crates/oxc_linter/src/rules/promise/no_multiple_resolved.rs:33
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::{Scoping, SymbolId};
use oxc_span::Span;
use rustc_hash::{FxHashMap, FxHashSet};
use crate::{
AstNode, context::LintContext, rule::Rule, utils::get_promise_constructor_inline_executor,
};
fn already_resolved_diagnostic(line: usize, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(
"Promise should not be resolved multiple times. Promise is already resolved on line {line}."
))
.with_label(span)
}
fn potentially_already_resolved_diagnostic(line: usize, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("Promise should not be resolved multiple times. Promise is potentially resolved on line {line}.")).with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoMultipleResolved;
declare_oxc_lint!(
/// ### What it does
///
/// This rule warns of paths that resolve multiple times in executor functions of Promise constructors.
///
/// ### Why is this bad?
///
/// Multiple resolve/reject calls:
/// - Violate the Promise/A+ specification
/// - Have no effect on the Promise's behavior
/// - Make the code's intent unclear
/// - May indicate logical errors in the implementation
///View on GitHub (pinned to 36ec0ef2ba)
Solutions
- Make the branches exclusive: add `else` before the trailing `resolve(value)` or `return` inside the reject branch
- Guard the later settle with the inverse condition: `if (!error) resolve(value)`
- Delete whichever settle call is unreachable dead code
- Replace the wrapper with `util.promisify` or rewrite as an `async` function so there is exactly one settle
Example fix
// before
new Promise((resolve, reject) => {
fn((error, value) => {
if (error) {
reject(error)
}
resolve(value)
})
})
// after
new Promise((resolve, reject) => {
fn((error, value) => {
if (error) {
reject(error)
return
}
resolve(value)
})
}) Defensive patterns
Strategy: validation
Validate before calling
# the same rule covers the 'potentially' variant - run it in pre-commit/CI npx oxlint --promise/no-multiple-resolved src/
Prevention
- After any conditional `reject`, make the next `resolve` exclusive (`else`, `return`, or `if (!error)`)
- Run the linter locally before pushing; this variant only appears from path analysis of your edited executor
- In code review, check that loops containing settle calls have no settle after the loop
- Keep executors small - move the body out so settle calls are trivially auditable
When it happens
Trigger: `if (error) { reject(error) }` followed by an unconditional `resolve(value)` (reject branch may or may not run); a settle inside a nested `if` at any depth with a later unconditional settle; `if (foo) { ... if (bar) reject(e) ... } resolve(v)` where the inner reject only fires on some paths.
Common situations: Error-first callback wrappers missing the `else`; guard clauses partially covering paths; refactors that move code below an existing conditional reject; copy-pasted executors where only some branches were updated.
Related errors
- Promise should not be resolved multiple times. Promise is al
- 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@36ec0ef2ba (2026-08-20).
Data as JSON: /api/errors/838538089817d6dc.
Report an issue: GitHub.