{"record":{"id":"564acd6f7ad23833","repo":"moeru-ai/airi","slug":"invalid-chat-session-export-format","errorCode":null,"errorMessage":"Invalid chat session export format","messagePattern":"Invalid chat session export format","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/composables/use-data-maintenance.ts","lineNumber":85,"sourceCode":"  function deleteAllChatSessions() {\n    chatOrchestrator.cancelPendingSends()\n    chatStore.resetAllSessions()\n  }\n\n  async function exportChatSessions() {\n    const data = await chatStore.exportSessions()\n    return new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })\n  }\n\n  function isChatSessionsPayload(payload: unknown): payload is ChatSessionsExport {\n    if (!payload || typeof payload !== 'object')\n      return false\n    return (payload as { format?: string }).format === 'chat-sessions-index:v1'\n  }\n\n  async function importChatSessions(payload: Record<string, unknown>) {\n    if (!isChatSessionsPayload(payload))\n      throw new Error('Invalid chat session export format')\n    await chatStore.importSessions(payload)\n    return payload\n  }\n\n  async function resetSettingsState() {\n    await settingsStore.resetState()\n    audioSettingsStore.resetState()\n    live2dParamsStore.resetState()\n    live2dSettingsStore.resetState()\n    threeStore.resetModelStore()\n    mcpStore.resetState()\n    onboardingStore.resetSetupState()\n    airiCardStore.resetState()\n  }\n\n  async function deleteAllData() {\n    await deleteAllModels()\n    await resetProvidersSettings()","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/stage-ui/src/composables/use-data-maintenance.ts#L67-L103","documentation":"Thrown by importChatSessions() when the parsed JSON payload's top-level `format` field does not equal the literal 'chat-sessions-index:v1'. This is a structural guard: AIRI's chat-session export format is versioned with that magic string, and the importer refuses anything else before touching the session store. It protects importSessions() from foreign or stale-shape data.","triggerScenarios":"Calling importChatSessions() with a JSON object whose `format` field is missing, undefined, or a different value (e.g. an older export tagged 'chat-sessions:v0', a hand-edited file, or an unrelated JSON document). The type guard isChatSessionsPayload() returns false and the throw fires before chatStore.importSessions runs.","commonSituations":"User picks the wrong file in the import dialog (e.g. a settings export or arbitrary JSON). The file is an export from an older AIRI version that used a different format tag. The file was renamed/tampered with so the format field was stripped.","solutions":["Re-export chat sessions from AIRI via exportChatSessions() and import that file — its format field is always 'chat-sessions-index:v1'.","If importing an older export, open the JSON and set the top-level `format` field to 'chat-sessions-index:v1' only if the rest of the shape matches ChatSessionsExport; otherwise upgrade by re-exporting.","Verify the file was produced by this AIRI version and not corrupted: confirm `payload.format === 'chat-sessions-index:v1'` in a console before importing."],"exampleFix":"// before: importing arbitrary JSON\nawait importChatSessions(parsed)\n// after: guard before calling\nif (!parsed || parsed.format !== 'chat-sessions-index:v1') {\n  throw new Error(`Expected chat-sessions-index:v1, got ${parsed?.format ?? 'none'}`)\n}\nawait importChatSessions(parsed)","handlingStrategy":"type-guard","validationCode":"function isChatSessionsExport(payload: unknown): payload is { format: string } {\n  return !!payload && typeof payload === 'object'\n    && (payload as { format?: unknown }).format === 'chat-sessions-index:v1'\n}\n// run before importChatSessions:\nconst parsed = JSON.parse(text)\nif (!isChatSessionsExport(parsed)) {\n  throw new Error(`Refusing import: expected format 'chat-sessions-index:v1', got ${(parsed as any)?.format}`)\n}","typeGuard":"function isChatSessionsPayload(payload: unknown): payload is ChatSessionsExport {\n  if (!payload || typeof payload !== 'object')\n    return false\n  return (payload as { format?: string }).format === 'chat-sessions-index:v1'\n}","tryCatchPattern":"try {\n  await importChatSessions(parsed)\n}\ncatch (err) {\n  if (err instanceof Error && err.message === 'Invalid chat session export format') {\n    // show user-facing 'wrong file' message; do not retry with same payload\n  }\n  else throw err\n}","preventionTips":["Always export via exportChatSessions() and import the produced file unchanged.","Validate the format tag in the file picker before calling import.","Do not hand-edit exported JSON in a way that removes the format field."],"tags":["validation","data-import","chat-sessions","type-guard"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}