stablyai/orca · error

review file has expired; create a new one before sending

Error message

review file has expired; create a new one before sending

What it means

Thrown by getPendingBundleForUpload when bundleSubmissionId passes format validation but is not present in the pendingBundles map (after pruning). Pending bundles are short-lived in-memory entries created when a diagnostics bundle/review file is generated; they expire after a TTL or are discarded on app exit, so a stale or post-restart ID is gone.

Source

Thrown at src/main/ipc/diagnostics.ts:116

    bytes: bundle.bytes,
    spanCount: bundle.spanCount
  }
}

function getPendingBundleForUpload(bundleSubmissionId: unknown): {
  readonly bundle: CollectedBundle
  readonly payload: string
} {
  if (
    typeof bundleSubmissionId !== 'string' ||
    !/^[A-Za-z0-9_-]{16,64}$/.test(bundleSubmissionId)
  ) {
    throw new Error('bundleSubmissionId has invalid format')
  }
  prunePendingBundles()
  const pending = pendingBundles.get(bundleSubmissionId)
  if (!pending) {
    throw new Error('review file has expired; create a new one before sending')
  }
  if (!pending.previewOpened) {
    throw new Error('open the review file before sending')
  }
  // Why: the preview file is user-editable once opened in the OS. Upload only
  // the redacted bytes main collected and retained before preview.
  return { bundle: pending.bundle, payload: pending.bundle.payload }
}

function getPendingPreviewFilePath(bundleSubmissionId: unknown): string {
  if (
    typeof bundleSubmissionId !== 'string' ||
    !/^[A-Za-z0-9_-]{16,64}$/.test(bundleSubmissionId)
  ) {
    throw new Error('bundleSubmissionId has invalid format')
  }
  prunePendingBundles()
  const pending = pendingBundles.get(bundleSubmissionId)

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Create a new review/diagnostics bundle to get a fresh bundleSubmissionId, then send within the same session.
  2. Send the review file promptly after creating it, before the TTL expires.
  3. Avoid app restarts between create and send; if restarted, always regenerate the bundle.
Defensive patterns

Strategy: validation

Validate before calling

function hasPendingBundle(bundleSubmissionId: string): boolean {
  prunePendingBundles()
  return pendingBundles.has(bundleSubmissionId)
}

Type guard

function isPendingBundleFresh(id: string, map: Map<string, unknown>): boolean {
  return map.has(id)
}

Try / catch

try {
  return getPendingBundleForUpload(id)
} catch (error) {
  if (error instanceof Error && /expired; create a new one/.test(error.message)) {
    const fresh = await createReviewBundle(...)
    return getPendingBundleForUpload(fresh.bundleSubmissionId)
  }
  throw error
}

Prevention

When it happens

Trigger: Calling the send/upload IPC with a bundleSubmissionId from a previous app session, after the prune TTL elapsed, or after the bundle was already discarded. The format regex passed (so the ID is well-formed) but the map lookup missed.

Common situations: App was restarted between creating the review file and sending it; the user waited longer than the bundle TTL; the bundle was discarded by memory pressure/pruning; an old submission ID was reused after a reload.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/c28e0d2cf4fa1447. Report an issue: GitHub.