windmill-labs/windmill · error
<server error text> || Failed to sign multiplayer session
Error message
<server error text> || Failed to sign multiplayer session
What it means
signMultiplayerRequest's failure path: any non-OK response from POST /api/w/{workspace}/debug/sign_multiplayer causes the server's error text — or the fallback 'Failed to sign multiplayer session' when the body is empty — to be thrown. The multiplayer server will subsequently reject the WebSocket connection without a valid JWT, so collaboration cannot start.
Source
Thrown at frontend/src/lib/components/debug/debugUtils.ts:95
/**
* Sign a multiplayer session request. Returns a JWT token that the
* multiplayer server will verify before accepting the WebSocket connection.
*/
export async function signMultiplayerRequest(workspace: string): Promise<string> {
if (!workspace) {
throw new Error('No workspace selected')
}
const response = await fetch(`/api/w/${workspace}/debug/sign_multiplayer`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({})
})
if (!response.ok) {
const errorText = await response.text()
throw new Error(errorText || 'Failed to sign multiplayer session')
}
const data: { token: string } = await response.json()
return data.token
}
/**
* Get a user-friendly error message for debug errors
*/
export function getDebugErrorMessage(error: unknown): string {
const message = error instanceof Error ? error.message : String(error)
// Handle token verification errors from debugger
if (message.includes('Token verification failed') || message.includes('Debug token required')) {
if (message.includes('expired')) {
return 'Debug session expired. Please try again.'
}
if (message.includes('Invalid JWT signature')) {View on GitHub (pinned to e474e8803c)
Solutions
- Read the thrown text / network status to identify the rejection; for 401/403 refresh the login or permissions.
- Confirm the backend build supports sign_multiplayer (EE/multiplayer enabled) — a 404 means the route is absent.
- Retry after transient 5xx/proxy errors; check backend logs if persistent.
- Verify the workspace id exists and the user is a member.
Defensive patterns
Strategy: try-catch
Try / catch
try { const token = await signMultiplayerRequest(ws) } catch (e) { disableCollaboration((e as Error).message); } Prevention
- Treat sign failure as 'collaboration unavailable' and degrade gracefully instead of crashing.
- Retry with backoff only on 5xx/network errors, not on 401/403.
- Re-sign when the underlying auth token refreshes.
When it happens
Trigger: Non-2xx from /debug/sign_multiplayer: 401/403 (expired/insufficient token), 404 (workspace not found or route absent on this backend version), 5xx from backend or proxy, or empty error body triggering the fallback.
Common situations: Session token expired while the editor stayed open; user lacking multiplayer entitlement (EE feature); backend version without the sign_multiplayer route; reverse proxy 502/503 during deploys.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- <server error text> || Failed to authorize debug session
- ApiError with mapped HTTP status message (e.g. "Not Found",
- Generic Error: status: ${errorStatus}; status text: ${errorS
- Couldn't fetch resource types from hub ${hubBaseUrl}: ${(awa
- Couldn't fetch resource types from public hub:
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/dbb769422886b500.
Report an issue: GitHub.