{"record":{"id":"589aced528bc654d","repo":"moeru-ai/airi","slug":"failed-to-create-character","errorCode":null,"errorMessage":"Failed to create character","messagePattern":"Failed to create character","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/services/characters.ts","lineNumber":185,"sourceCode":"    return data.map((item: unknown) => parse(item))\n  }\n\n  async function fetchRemoteById(client: CharactersRemoteClient, id: string, options?: CharacterServiceOptions): Promise<Character> {\n    options?.abortSignal?.throwIfAborted()\n    const res = await client.api.v1.characters[':id'].$get({ param: { id } }, requestOptions(options))\n    if (!res.ok)\n      throw new Error('Failed to fetch character')\n\n    const data = await res.json()\n    options?.abortSignal?.throwIfAborted()\n    return parse(data)\n  }\n\n  async function createRemote(client: CharactersRemoteClient, payload: CreateCharacterPayload, options?: CharacterServiceOptions): Promise<Character> {\n    options?.abortSignal?.throwIfAborted()\n    const res = await client.api.v1.characters.$post({ json: payload }, requestOptions(options))\n    if (!res.ok)\n      throw new Error('Failed to create character')\n\n    const data = await res.json()\n    options?.abortSignal?.throwIfAborted()\n    return parse(data)\n  }\n\n  async function updateRemote(client: CharactersRemoteClient, id: string, payload: UpdateCharacterPayload, options?: CharacterServiceOptions): Promise<Character> {\n    options?.abortSignal?.throwIfAborted()\n    const res = await client.api.v1.characters[':id'].$patch({\n      param: { id },\n      json: payload,\n    }, requestOptions(options))\n    if (!res.ok)\n      throw new Error('Failed to update character')\n\n    const data = await res.json()\n    options?.abortSignal?.throwIfAborted()\n    return parse(data)","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/stage-ui/src/services/characters.ts#L167-L203","documentation":"Thrown by CharactersService.createRemote when POST /v1/characters returns non-ok. The service sends a CreateCharacterPayload as JSON and expects a parseable character back. Failure means the server rejected the create (validation, auth, conflict) before a character was persisted.","triggerScenarios":"client.api.v1.characters.$post({ json: payload }) resolves with ok=false. Typical: 400 (payload fails server-side validation, e.g. missing required fields, invalid name), 401/403 (not authenticated or lacking create permission), 409 (duplicate slug/name), 500 (server).","commonSituations":"Submitted character form with missing/invalid fields; session expired mid-edit; backend schema changed and the client payload no longer matches; uniqueness constraint violation on name/slug.","solutions":["Validate the CreateCharacterPayload client-side (required fields, length limits) before posting.","Re-authenticate if the session expired, then retry the create.","Capture res.status and body to surface field-level validation errors to the form.","On 409 conflict, prompt the user to pick a unique name."],"exampleFix":"// before\nif (!res.ok)\n  throw new Error('Failed to create character')\n\n// after: expose server validation detail\nif (!res.ok) {\n  const detail = await res.json().catch(() => null)\n  throw new CreateCharacterError(`Failed to create character (status ${res.status})`, detail)\n}","handlingStrategy":"validation","validationCode":"import { CharacterWithRelationsSchema } from '../../types/character'\n\nfunction validateCreatePayload(payload: CreateCharacterPayload): string[] {\n  const errors: string[] = []\n  if (!payload.name?.trim())\n    errors.push('name is required')\n  // add other required-field checks matching server schema\n  return errors\n}\n\nconst issues = validateCreatePayload(payload)\nif (issues.length)\n  throw new Error('Invalid payload: ' + issues.join(', '))\nawait createRemote(client, payload)","typeGuard":null,"tryCatchPattern":"try {\n  return await createRemote(client, payload)\n}\ncatch (error) {\n  // Patch service to surface res.status + body; map 400/422 to form field errors.\n  // On 401/403 re-authenticate; on 409 prompt for unique name.\n  throw error\n}","preventionTips":["Validate CreateCharacterPayload client-side against the same rules the server enforces.","Embed res.status and server validation detail in the service error for form feedback.","Re-authenticate on 401/403 before retrying the create."],"tags":["network","http","characters","api","validation","auth"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}