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

  1. 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.
  2. Check that no proxy/middleware between client and broker strips or delays the first SSE frame (some proxies buffer or drop the initial event).
  3. Catch AuthBrokerError from openSnapshotStream and fall back to the long-polling path (AuthBrokerClient.fetchSnapshot), which fetches the snapshot over plain JSON.
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/26f0f6b9f6da33c1. Report an issue: GitHub.