chatboxai/chatbox · error

Resource was not staged: ${resource.path}

Error message

Resource was not staged: ${resource.path}

What it means

Thrown by createResourcePlans when a manifest resource's path has no staged entry or its staged entry lacks a tempKey. Reading normally stages every resource under a temp blob key (lines 244-248); reaching this throw means staging and the manifest disagree. Propagates after rollback.

Source

Thrown at src/renderer/packages/backup/import-backup.ts:137

      }
    }
    const candidate = `${candidatePrefix}:${uuidv4()}`
    if (!reserved.has(candidate) && (await storage.getBlob(candidate)) === null) return candidate
  }
  throw new Error(`Could not allocate a resource key for: ${originalKey}`)
}

async function createResourcePlans(
  manifest: BackupManifest,
  stagedEntries: Map<string, StagedEntry>,
  storage: BackupStorage
) {
  const plans: ResourceWritePlan[] = []
  const resourceKeyMap = new Map<string, string>()
  const reserved = new Set<string>()
  for (const resource of manifest.resources) {
    const staged = stagedEntries.get(resource.path)
    if (!staged?.tempKey) throw new Error(`Resource was not staged: ${resource.path}`)
    const restoredValue = await readStagedResource(storage, { resource, tempKey: staged.tempKey })
    const targets: ResourceWritePlan['targets'] = []
    for (const originalKey of resource.originalStorageKeys) {
      const existingValue = await storage.getBlob(originalKey)
      let targetKey = originalKey
      let needsWrite = existingValue === null
      if (existingValue !== null && existingValue !== restoredValue) {
        targetKey = await findAvailableCollisionKey(storage, originalKey, reserved)
        needsWrite = true
      }
      if (reserved.has(targetKey)) {
        targetKey = await findAvailableCollisionKey(storage, originalKey, reserved)
        needsWrite = true
      }
      reserved.add(targetKey)
      resourceKeyMap.set(originalKey, targetKey)
      targets.push({ originalKey, targetKey, needsWrite })
    }

View on GitHub (pinned to 81571269ad)

Solutions

  1. Ensure validateManifestEntries runs before createResourcePlans (it does in importBackupArchive).
  2. Confirm isBackupResourcePath classifies every manifest resource path as a resource during the reading phase.
  3. If the manifest was edited, restore it so it matches the archive.
  4. Regenerate the backup.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before import, ensure every resource path was staged with a tempKey during reading.
for (const r of manifest.resources) {
  const staged = stagedEntries.get(r.path)
  if (!staged?.tempKey) throw new Error('Resource not staged: ' + r.path)
}

Try / catch

try {
  await importBackupArchive(file, options)
} catch (error) {
  if (error instanceof Error && error.message.startsWith('Resource was not staged')) {
    // Usually means validateManifestEntries was bypassed; re-run it before createResourcePlans.
    throw new Error('Resource staging incomplete', { cause: error })
  }
  throw error
}

Prevention

When it happens

Trigger: manifest.resources[i].path is absent from stagedEntries, or its staged entry has tempKey undefined when createResourcePlans runs.

Common situations: Normally caught earlier by validateManifestEntries (error 126). Reachable if validation was skipped, if a resource path was staged via the JSON branch instead of the resource branch due to an isBackupResourcePath mismatch, or if tempKey assignment changed.

Related errors


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