wandb/openui · error · Error

Unexpected response ${req.status}: ${await req.text()}

Error message

Unexpected response ${req.status}: ${await req.text()}

What it means

post() sends JSON to the backend (used by register and auth for the WebAuthn ceremony result) and expects 200. Any other status throws an Error with the status and raw body text, which the callers' catch blocks then interpret.

Source

Thrown at frontend/src/api/openui.ts:163

			client_data_json: asBase64(clientDataJSON),
			signature: asBase64(signature),
			authenticator_data: asBase64(authenticatorData)
		}
	}
	const req = await fetch(
		`${API_HOST}/${create ? 'register' : 'auth'}/${encodeURIComponent(
			username
		)}`,
		{
			credentials: 'same-origin',
			method: 'POST',
			body: JSON.stringify(data),
			headers: { 'content-type': 'application/json' }
		}
	)

	if (req.status !== 200) {
		throw new Error(`Unexpected response ${req.status}: ${await req.text()}`)
	}
}

export async function register(username: string): Promise<boolean> {
	try {
		const publicKey = (await getPublicKey(
			username,
			true
		)) as PublicKeyCredentialCreationOptions
		console.log('registration response:', publicKey.user, typeof publicKey.user)
		publicKey.user.id = asArrayBuffer(publicKey.user.id as unknown as string)
		publicKey.challenge = asArrayBuffer(
			publicKey.challenge as unknown as string
		)
		const creds = await navigator.credentials.create({ publicKey })
		await post(username, creds as PublicKeyCredential, true)
		return true
	} catch (error) {

View on GitHub (pinned to 42d7ab4ab6)

Solutions

  1. Check response text for known strings like 'User already exists' and map them to friendly UI states (register already does this).
  2. Ensure cookies/session persist across getPublicKey and post (credentials: 'same-origin' is required).
  3. Retry the flow from getPublicKey if the challenge expired.
  4. Wrap register/auth in try/catch and show the parsed reason to the user.

Example fix

// before
throw new Error(`Unexpected response ${req.status}: ${await req.text()}`)
// after
const text = await req.text()
throw new Error(`WebAuthn post failed (${req.status}): ${text.slice(0, 200)}`)
Defensive patterns

Strategy: try-catch

Validate before calling

if (!credential || !credential.response) throw new Error('WebAuthn ceremony was cancelled or failed')

Type guard

function isRegistrationResponse(c: unknown): c is PublicKeyCredential {
  return typeof c === 'object' && c !== null && 'response' in (c as object)
}

Try / catch

try {
  return await register(username)
} catch (e) {
  if (String(e).includes('User already exists')) return false
  throw e
}

Prevention

When it happens

Trigger: Non-200 from POSTing the WebAuthn attestation/assertion: credential rejected or already registered, invalid challenge (expired), or missing session cookie.

Common situations: Registering a username that already exists (server returns 4xx whose text contains 'User already exists'); stale WebAuthn challenge after a page reload; browser cancelled the ceremony.

Related errors


AI-assisted analysis of wandb/openui@42d7ab4ab6 (2026-09-01). Data as JSON: /api/errors/235dc97cb697b6c6. Report an issue: GitHub.