{"record":{"id":"eb9e0b0f2b6d0ce0","repo":"wandb/openui","slug":"unkown-error-string-error","errorCode":null,"errorMessage":"Unkown error: ${String(error)}","messagePattern":"Unkown error: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"frontend/src/api/openui.ts","lineNumber":189,"sourceCode":"\t\t\ttrue\n\t\t)) as PublicKeyCredentialCreationOptions\n\t\tconsole.log('registration response:', publicKey.user, typeof publicKey.user)\n\t\tpublicKey.user.id = asArrayBuffer(publicKey.user.id as unknown as string)\n\t\tpublicKey.challenge = asArrayBuffer(\n\t\t\tpublicKey.challenge as unknown as string\n\t\t)\n\t\tconst creds = await navigator.credentials.create({ publicKey })\n\t\tawait post(username, creds as PublicKeyCredential, true)\n\t\treturn true\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\t// TODO: this is hacky but works\n\t\t\tif (error.toString().includes('User already exists')) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tthrow error\n\t\t} else {\n\t\t\tthrow new TypeError(`Unkown error: ${String(error)}`)\n\t\t}\n\t}\n}\n\nexport async function auth(username: string): Promise<boolean> {\n\tconst publicKey = (await getPublicKey(\n\t\tusername\n\t)) as PublicKeyCredentialRequestOptions\n\tconsole.log('auth get response:', publicKey)\n\tpublicKey.challenge = asArrayBuffer(publicKey.challenge as unknown as string)\n\tif (\n\t\tpublicKey.allowCredentials !== undefined &&\n\t\tpublicKey.allowCredentials.length > 0\n\t) {\n\t\tpublicKey.allowCredentials[0].id = asArrayBuffer(\n\t\t\tpublicKey.allowCredentials[0].id as unknown as string\n\t\t)\n\t\t// TODO: if a user attempts to re-register they'll be given the option","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/wandb/openui/blob/42d7ab4ab6650433486dfb12eb3783c393a3e475/frontend/src/api/openui.ts#L171-L207","documentation":"register() catches errors from the WebAuthn flow; if the message contains 'User already exists' it returns false, otherwise it rethrows. If the caught value is NOT an Error instance (else branch) it wraps it in a TypeError with 'Unkown error: <string>'. This happens when a non-Error (string, DOMException-like value, undefined) is thrown or rejected.","triggerScenarios":"The WebAuthn ceremony rejects with a non-Error value (e.g. NotAllowedError is fine, but some browsers/polyfills throw strings); or getPublicKey/post reject with undefined.","commonSituations":"User cancels the passkey prompt in browsers that throw non-Error values; older Safari/Chrome WebAuthn quirks; promise rejection with a plain string from a custom layer.","solutions":["Normalize caught values with `error instanceof Error ? error : new Error(String(error))` before branching.","Keep the 'User already exists' substring check but base it on String(error).","Fix the typo 'Unkown' → 'Unknown' when surfacing the message.","Log the raw thrown value to identify which browser/path produces non-Error rejections."],"exampleFix":"// before\nthrow new TypeError(`Unkown error: ${String(error)}`)\n// after\nthrow error instanceof Error\n  ? error\n  : new Error(`Unknown error: ${String(error)}`)","handlingStrategy":"type-guard","validationCode":"if (typeof username !== 'string' || username.length === 0) throw new Error('Username required')","typeGuard":"function isError(v: unknown): v is Error {\n  return v instanceof Error\n}","tryCatchPattern":"try {\n  await register(username)\n} catch (e) {\n  if (String(e).includes('User already exists')) return false\n  if (e instanceof Error) throw e\n  throw new Error(`Unknown error: ${String(e)}`)\n}","preventionTips":["Normalize all caught values with instanceof Error before branching","Check for existing users before registering","Log raw thrown values to catch browser-specific non-Error rejections"],"tags":["typescript","webauthn","error-handling"],"backgroundTag":"non-error-thrown-value","analyzedSha":"42d7ab4ab6650433486dfb12eb3783c393a3e475","analyzedAt":"2026-09-01T05:00:32.200Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}