can1357/oh-my-pi · error · AuthBrokerError
Auth broker stream did not start with snapshot
Error message
Auth broker stream did not start with snapshot
What it means
openSnapshotStream consumes the broker's SSE snapshot stream and enforces the protocol contract that the first event frame must be a full `snapshot` event (client.ts:253-257). If the first parsed, schema-valid SnapshotStreamEvent has kind !== "snapshot", the client cannot establish a baseline credential state, so it throws AuthBrokerError immediately rather than yielding events on top of a missing baseline. This protects consumers like RemoteAuthCredentialStore from applying incremental `entry`/`removed` deltas against a state that was never initialized.
Source
Thrown at packages/ai/src/auth-broker/client.ts:256
try {
parsed = JSON.parse(sse.data);
} catch (err) {
throw new AuthBrokerError("Auth broker stream returned malformed JSON", {
body: sse.data,
cause: err,
});
}
const validated = snapshotStreamEventSchema(parsed);
if (validated instanceof type.errors) {
throw new AuthBrokerError("Auth broker stream event failed schema validation", {
body: validated.summary,
});
}
const event = validated as SnapshotStreamEvent;
if (!sawFirstEvent) {
sawFirstEvent = true;
if (event.kind !== "snapshot") {
throw new AuthBrokerError("Auth broker stream did not start with snapshot", { body: sse.data });
}
}
yield event;
}
if (!opts.signal?.aborted) {
throw new AuthBrokerError(
sawFirstEvent
? "Auth broker stream ended unexpectedly"
: "Auth broker stream ended before initial snapshot",
{ status: response.status },
);
}
}
/**
* Fetch aggregate broker usage with a timeout sized for serialized
* same-provider account probes.
*/View on GitHub (pinned to 9690622007)
Solutions
- Verify the broker is running a version whose /v1/snapshot/stream endpoint emits a full snapshot as the first event; upgrade or redeploy the auth-broker server to match the client.
- Check that no proxy/middleware between client and broker strips or delays the first SSE frame (some proxies buffer or drop the initial event).
- Catch AuthBrokerError from openSnapshotStream and fall back to the long-polling path (AuthBrokerClient.fetchSnapshot), which fetches the snapshot over plain JSON.
- If you run a mock/custom broker, make its first emitted frame `{ kind: "snapshot", ... }` matching snapshotStreamEventSchema.
Example fix
// before
for await (const event of client.openSnapshotStream({ signal })) {
applyEvent(event);
}
// after
try {
for await (const event of client.openSnapshotStream({ signal })) {
applyEvent(event);
}
} catch (err) {
if (err instanceof AuthBrokerError && err.message.includes("did not start with snapshot")) {
logger.warn("snapshot stream protocol mismatch, falling back to polling", { body: err.body });
await pollSnapshotLoop(signal);
} else {
throw err;
}
} Defensive patterns
Strategy: try-catch
Type guard
function isSnapshotFirstProtocolError(err: unknown): err is AuthBrokerError {
return err instanceof AuthBrokerError && err.message === "Auth broker stream did not start with snapshot";
} Try / catch
try {
for await (const event of client.openSnapshotStream({ signal })) {
applyEvent(event);
}
} catch (err) {
if (isSnapshotFirstProtocolError(err)) {
logger.warn("broker stream protocol violation, falling back to polling", { body: err.body });
await startPollingFallback(signal);
} else {
throw err;
}
} Prevention
- Pin broker and client to matching versions; protocol changes ship in lockstep.
- Test SSE integrations against a mock that emits `{ kind: "snapshot" }` as frame 1.
- Add an integration test that asserts the first streamed event kind is "snapshot".
- Avoid proxies that transform or buffer SSE traffic on the broker path.
When it happens
Trigger: Calling AuthBrokerClient.openSnapshotStream() against a broker that emits its first SSE data frame with kind "entry", "refresh", or "removed" instead of kind "snapshot" — i.e. a server violating the documented stream protocol where frame #1 must be a full snapshot.
Common situations: Running a broker server built from a different or older/newer version of the protocol than the client expects; a custom or proxy SSE endpoint that forwards mid-stream deltas from an already-active session (joining the stream after the initial snapshot was emitted); a misconfigured reverse proxy or load balancer that drops the first event frame; testing against a mock broker that only emits upserts.
Related errors
- Auth broker stream ended unexpectedly
- Auth broker stream ended before initial snapshot
- received ${event.type} before message_start
- V2 compaction stream closed before response.completed
- V2 compaction stream parse failed: ${err instanceof Error ?
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/26f0f6b9f6da33c1.
Report an issue: GitHub.