chatboxai/chatbox · warning · Error

Session is missing or invalid

Error message

Session is missing or invalid

What it means

Thrown while iterating session ids during backup export after fetching the Session stored under backupSessionStorageKey(id). It fires when the value is null yet metadata still references that id, or when a non-null value fails the isBackupSession shape check (non-empty string id, string name, array messages). The throw is caught one frame up (lines 277-284) and recorded as a 'session-read-failed' warning, so export continues and the message surfaces in result.manifest.warnings rather than aborting.

Source

Thrown at src/renderer/packages/backup/export-backup.ts:259

      const metaById = new Map(allMeta.map((meta) => [meta.id, meta]))
      const sessionIds = unique([
        ...allMeta.map((meta) => meta.id),
        ...allStorageKeys.filter((key) => key.startsWith('session:')).map((key) => key.slice('session:'.length)),
      ])

      for (let index = 0; index < sessionIds.length; index++) {
        throwIfAborted(options.signal)
        const sessionId = sessionIds[index]
        options.onProgress?.({
          phase: 'sessions',
          current: index,
          total: sessionIds.length,
          label: metaById.get(sessionId)?.name,
        })
        try {
          const session = await options.storage.getItem<Session | null>(backupSessionStorageKey(sessionId), null)
          if (session === null && !metaById.has(sessionId)) continue
          if (!isBackupSession(session)) throw new Error('Session is missing or invalid')
          if (session.id !== sessionId) throw new Error('Session id does not match its storage key')
          const collected = collectSessionResourceReferences(session)
          const preparedSession = prepareSessionForBackup(session)
          const path = `sessions/${await safeSessionPathComponent(session.id)}/session.json`
          const { archive, descriptor } = await jsonEntry(path, preparedSession)
          warnings.push(...collected.warnings)
          addResourceReferences(resourceCandidates, collected.references)
          sessions.push({
            entry: {
              ...descriptor,
              id: session.id,
              meta: deriveSessionMeta(preparedSession, metaById.get(session.id)),
              resourceIds: [],
            },
            resourceStorageKeys: new Set(collected.references.map((reference) => reference.storageKey)),
          })
          yield archive
        } catch (error) {

View on GitHub (pinned to 81571269ad)

Solutions

  1. Prune orphaned meta records and 'session:' keys before exporting (meta without a valid session value, and session values without meta).
  2. Ensure session writes are atomic so a crash never leaves a malformed Session value in storage.
  3. If the data is genuinely corrupt, delete the offending session value so line 258 skips it cleanly instead of producing a warning.
  4. Set exportItems to exclude 'conversations' to bypass session iteration entirely when only settings/copilots are needed.

Example fix

// before: orphaned meta causes a warning each export
await exportBackupArchive(options)
// after: drop meta rows whose session value is invalid/unreadable
const allMeta = await metaStorage.getAllIncludingHidden()
for (const meta of allMeta) {
  const session = await storage.getItem('session:' + meta.id, null)
  if (!isBackupSession(session)) await metaStorage.delete(meta.id)
}
await exportBackupArchive(options)
Defensive patterns

Strategy: validation

Validate before calling

// Before export, detect orphaned meta / unreadable sessions so no warning fires.
const allMeta = await metaStorage.getAllIncludingHidden()
const orphans: string[] = []
for (const meta of allMeta) {
  const session = await storage.getItem('session:' + meta.id, null)
  if (!isBackupSession(session)) orphans.push(meta.id)
}
if (orphans.length) console.warn('Orphaned sessions will be skipped:', orphans)

Type guard

import { isBackupSession } from './archive-layout'
// Returns true only when value is an object with non-empty string id,
// string name, and array messages - the exact shape this error checks.
const sessionIsExportable = (v: unknown): v is Session => isBackupSession(v)

Prevention

When it happens

Trigger: A session id appears in metaStorage.getAllIncludingHidden() or as a 'session:' storage key, but the corresponding Session value is absent, partially written, or structurally incomplete (missing/non-string/empty id, missing name, or messages not an array). The guard at line 258 only skips when session===null AND metaById has no entry, so an orphaned meta record falls through to isBackupSession(null) and throws.

Common situations: Leftover meta records after a session was deleted without removing its meta row; a crashed prior write that left a half-serialized session; a storage migration that dropped required fields; concurrent edits to sessions during export.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/b04a8e20f5294595. Report an issue: GitHub.