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

  1. Await each fluent builder call (or the final call of the chain) so promises resolve explicitly and the warning disappears.
  2. If intentionally fire-and-forget, capture the promise and await it later at a defined point rather than relying on implicit flush.
  3. 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

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


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)