block/buzz · error · Error
Relay publish was superseded by a session change.
Error message
Relay publish was superseded by a session change.
What it means
relayClientSession compares the caller's connection generation with the session's current generation right before sending raw JSON over the Tauri websocket plugin. If the connection was re-established (generation bumped) or wsId became null, the payload would go over a stale socket, so it throws. This is a stale-socket fence for publishes.
Source
Thrown at desktop/src/shared/api/relayClientSession.ts:656
}
private async sendRaw(payload: unknown[]) {
if (this.wsId === null) {
throw new Error("Relay socket is not connected.");
}
await invoke("plugin:websocket|send", {
id: this.wsId,
message: {
type: "Text",
data: JSON.stringify(payload),
},
});
}
private async sendRawForGeneration(payload: unknown[], generation: number) {
if (generation !== this.connectionGeneration || this.wsId === null) {
throw new Error("Relay publish was superseded by a session change.");
}
const wsId = this.wsId;
await invoke("plugin:websocket|send", {
id: wsId,
message: { type: "Text", data: JSON.stringify(payload) },
});
}
private normalizeRelayError(error: unknown, fallbackMessage: string) {
return error instanceof Error ? error : new Error(fallbackMessage);
}
private recoverFromSocketFailure(
error: unknown,
fallbackMessage: string,
): Error {
const normalizedError = this.normalizeRelayError(error, fallbackMessage);
this.resetConnection(normalizedError);View on GitHub (pinned to 6c35e82bd5)
Solutions
- Catch the error and re-publish using a freshly obtained generation (e.g. via session.reconnect()).
- Avoid holding publishes across community switches; cancel or re-dispatch them after the switch.
- Serialize publishes through the session so each uses its current generation.
- Surface a retry affordance to the user for failed outbound messages.
Example fix
// before
try { await send(payload, oldGeneration); } catch {}
// after
try { await send(payload, oldGeneration); }
catch (e) {
if (isSuperseded(e)) { const gen = await session.reconnect(); await send(payload, gen); }
else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// verify session generation freshness before send if (generation !== session.currentGeneration()) await session.reconnect();
Type guard
function isSupersededError(e: unknown): boolean { return e instanceof Error && e.message.includes('superseded by a session change'); }
Try / catch
try { await publishEvent(ev); } catch (e) { if (isSupersededError(e)) await publishEvent(ev); else throw e; }
Prevention
- Capture generation as late as possible before sending
- Route all reconnects through the session object
- Cancel in-flight publishes during community switches
When it happens
Trigger: sendRawForGeneration invoked with a generation captured before a reconnect/community switch completed; concurrent publish racing a session teardown that nulled wsId.
Common situations: Community switch while a publish is in flight; automatic reconnect after network blip; publish queued during rate-limit wait then sent on a replaced socket.
Related errors
- Read-only relay socket is not connected.
- repo announcement lost community serving lease: {error}
- Relay disconnected for community switch.
- Relay publish was superseded by a session change.
- setup-mode membership subscribe error: {e}
AI-assisted analysis of block/buzz@6c35e82bd5 (2026-09-05).
Data as JSON: /api/errors/3e9184a48f8e2fc7.
Report an issue: GitHub.