microsoft/aspire · warning
Flushing pending promise(s). Consider awaiting fluent calls…
Error message
Flushing ${this._pendingPromises.size} pending promise(s). Consider awaiting fluent calls to avoid implicit flushing. What it means
The TypeScript code-generation transport tracks Promises created by fluent builder calls that were not awaited. When an implicit flush point is reached while unawaited promises are still pending, flushPendingPromises awaits them (allSettled) and warns that the user should await fluent calls explicitly. It is a diagnostic warning about potentially unintended fire-and-forget execution order.
Solutions
- Await each fluent builder call (or the final call of the chain) so promises resolve explicitly and the warning disappears.
- If intentionally fire-and-forget, capture the promise and await it later at a defined point rather than relying on implicit flush.
- Check that build/emit entry points await flushPendingPromises (or the build completion API) before process exit so no promises are dropped.
Example fix
// before
builder.addEndpoint("http").withPort(8080);
// after
await builder.addEndpoint("http").withPort(8080); Defensive patterns
Strategy: validation
Validate before calling
// Ensure fluent chains are awaited at build time before flushing.
if (typeof promise?.then !== 'function') throw new TypeError('Expected a thenable from fluent call');
await promise; // always await before starting another operation Type guard
function isPromiseLike(v) { return v != null && typeof v.then === 'function'; } Try / catch
process.on('warning', (w) => {
if (String(w.message).includes('pending promise(s)')) {
// audit code paths that skip await on fluent calls
}
}); Prevention
- Always await fluent builder calls, including the last call of a chain.
- Enable lint rules (e.g. @typescript-eslint/no-floating-promises) to catch missing awaits.
- Do not rely on implicit flushing for ordering; flush explicitly at defined points.
When it happens
Trigger: Calling fluent generator methods (e.g. chained builder operations) without await, so their Promises accumulate in _pendingPromises, and then hitting a flush boundary (another awaited operation or completion) that forces flushPendingPromises to settle them.
Common situations: Omitting 'await' on a fluent call in generated TypeScript code; relying on implicit flushing at the end of a build; mixing awaited and unawaited calls leading to nondeterministic ordering warnings during codegen runs.
Related errors
- Argument ' ' passed to capability ' ' is a Promise-like…
- AspireDict must be resolved before it can be serialized…
- AspireList must be resolved before it can be serialized…
- The operation was aborted before it was sent to the AppHost.
- Argument ' ' passed to capability ' ' contains a circular…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/0a361fa76025e599.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/transport.mts:802
// rejections will also be re-thrown by build(). We accept this tradeoff
// because the common case — an un-awaited chain fails silently — should
// fail loud. The uncommon case (catch an error from an un-awaited chain,
// then continue to build) can opt out with:
// createBuilder({ throwOnPendingRejections: false })
promise.then(
() => this._pendingPromises.delete(promise),
(err) => {
this._pendingPromises.delete(promise);
if (this.throwOnPendingRejections) {
this._rejectedErrors.add(err);
}
}
);
}
async flushPendingPromises(): Promise<void> {
if (this._pendingPromises.size > 0) {
console.warn(`Flushing ${this._pendingPromises.size} pending promise(s). Consider awaiting fluent calls to avoid implicit flushing.`);
// Snapshot the current set before awaiting. Promises tracked after
// flush starts (e.g. by .then() callbacks or the build PromiseImpl
// constructor) are excluded. This prevents deadlocks where a tracked
// promise depends on flush completing.
const pending = [...this._pendingPromises];
await Promise.allSettled(pending);
}
if (this._rejectedErrors.size > 0) {
const errors = [...this._rejectedErrors];
this._rejectedErrors.clear();
throw new AggregateError(errors, 'One or more unawaited fluent calls failed');
}
}
/**
* Register a callback to be called when the connection is lost
*/
onDisconnect(callback: () => void): void {View on GitHub (pinned to 25830f84bd)