github/copilot-sdk · warning

Ignoring a background factory progress flush failure after…

Error message

Ignoring a background factory progress flush failure after the factory body settled

What it means

Not a thrown exception but a console warning emitted from close() (nodejs/src/session.ts:287): when the background factory-progress flush task (flushTail) previously failed (flushFailed set) while the session was streaming, close() awaits it and then logs this warning with the stored flushError. It tells the developer some progress events may not have been flushed, but close() continues deliberately and does not fail.

Solutions

  1. Check the accompanying flushError in the warning for the underlying stream failure
  2. Verify the destination stream/pipe stayed writable for the session's lifetime (file handle not closed early, pipe consumer alive)
  3. Drain/await pending progress lines before closing, or re-persist the lines pending at close()
  4. Treat the warning as a data-loss signal: re-send or log the unflushed progress events

Example fix

// before
await session.close(); // flush failure only surfaces as a console warning
// after
if (session.flushFailed) await persistProgress(session.pendingLines);
await session.close();
Defensive patterns

Strategy: try-catch

Validate before calling

// before close, ensure the stream is still writable
if (session.outputStream.destroyed || session.outputStream.writableEnded) {
  console.warn('Progress output stream already closed; progress may be lost');
}

Type guard

function hasFlushError(s) {
  return s.flushFailed === true && s.flushError instanceof Error;
}

Try / catch

try {
  await session.close();
} catch (err) {
  console.error('close failed', err); // the flush warning itself is non-fatal
} finally {
  if (session.flushFailed) persistProgress(session.pendingLines); // recover unflushed data
}

Prevention

When it happens

Trigger: Calling session.close() after a background flush of pending factory progress lines already rejected asynchronously (stream errored, pipe broken, or disk full mid-flight), so this.flushFailed is true and this.flushError is set when close() awaits this.flushTail.

Common situations: Output stream (file/pipe/socket) was closed or broke while the session was still running; process exit raced a pending flush; disk-full or EPIPE caused a flush rejection and the timer-driven retry also failed.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/e172244cf0c90f46. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/src/session.ts:287

                        this.flushFailed = true;
                        this.flushError = error;
                    }
                }
            });
        }
        await this.flushTail;
        if (this.flushFailed) {
            throw this.flushError;
        }
    }

    async close(): Promise<void> {
        this.closed = true;
        this.clearFlushTimer();
        const lines = this.pending.splice(0);
        await this.flushTail;
        if (this.flushFailed) {
            console.warn(
                "Ignoring a background factory progress flush failure after the factory body settled",
                this.flushError
            );
        }
        if (lines.length > 0) {
            try {
                await this.send(lines);
            } catch (error) {
                console.warn(
                    "Failed to flush final factory progress after the factory body settled",
                    error
                );
            }
        }
    }

    private scheduleFlush(): void {
        if (this.flushTimer !== undefined) {

View on GitHub (pinned to cd8cf15dc3)