stablyai/orca · error

Artifact share records could not be read safely.

Error message

Artifact share records could not be read safely.

What it means

Thrown by the share-record store reader when JSON.parse(readFileSync(recordPath)) fails — the share-record JSON file exists but its content is unparseable. The original error is attached as `cause`. This is the read-level counterpart to the format check at 753 and only signals JSON corruption, not a schema mismatch.

Solutions

  1. Read error.cause for the JSON parse offset and inspect the file around that byte.
  2. If unrecoverable, back up then delete the share-record file — a fresh empty store ({version:2,...}) will be recreated on next access; re-share artifacts as needed.
  3. Ensure the writer uses atomic write-temp-then-rename so concurrent writes/crashes cannot corrupt the file.

Example fix

// before
const records = readShareRecords(...) // JSON.parse throws

// after
try { return readShareRecords(...) }
catch (e) {
  if (e.cause instanceof SyntaxError) await restoreFromBackupOrReset(profileId, userDataPath)
  throw
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { readFileSync } from 'node:fs'

function isShareRecordJsonParseable(path: string): boolean {
  try { JSON.parse(readFileSync(path, 'utf8')); return true } catch { return false }
}

if (existsSync(path) && !isShareRecordJsonParseable(path)) {
  await fs.promises.rename(path, `${path}.corrupt`)
}

Type guard

function isJsonParseError(e: unknown): boolean {
  return e instanceof SyntaxError || (e instanceof Error && e.cause instanceof SyntaxError)
}

Try / catch

try {
  return readShareRecords(profileId, userDataPath)
} catch (e) {
  if (isJsonParseError(e)) {
    await backupAndResetShareRecords(profileId, userDataPath)
    return { version: 2, lifecycleGeneration: 0, lifecycleNonce: '', shares: {} }
  }
  throw e
}

Prevention

When it happens

Trigger: A partial write left truncated JSON in the share-record file; encoding/BOM mangling; a non-JSON file overwritten the record path; the process was killed mid-write before the file was complete.

Common situations: Power loss during a share-record update (non-atomic write); a sync/backup tool rewrote the file with conflicts; a hand-edit introduced a syntax error; antivirus quarantined then restored a partial file.

Related errors


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

Appendix: source

Thrown at src/main/artifacts/artifact-share-record-store.ts:116

    changed: retained.length !== currentEntries.length
  }
}

function readRecords(
  profileId: string,
  userDataPath: string,
  preserveExpired?: { sourceKey: string; slug: string; editToken: string },
  pruneExpired = true
): ArtifactShareRecordFile {
  const path = recordPath(profileId, userDataPath)
  if (!existsSync(path)) {
    return { version: 2, lifecycleGeneration: 0, lifecycleNonce: '', shares: {} }
  }
  let parsed: ParsedArtifactShareRecordFile
  try {
    parsed = JSON.parse(readFileSync(path, 'utf8')) as ParsedArtifactShareRecordFile
  } catch (error) {
    throw new Error('Artifact share records could not be read safely.', { cause: error })
  }
  if (parsed.version === 1) {
    return { version: 2, lifecycleGeneration: 0, lifecycleNonce: '', shares: {} }
  }
  if (
    parsed.version !== 2 ||
    !parsed.shares ||
    typeof parsed.shares !== 'object' ||
    Array.isArray(parsed.shares)
  ) {
    throw new Error('Artifact share records have an unsupported format.')
  }
  const shareEntries = Object.entries(parsed.shares as Record<string, unknown>)
  const validShares = Object.fromEntries(
    shareEntries.filter((entry): entry is [string, ArtifactShareRecord] => isRecord(entry[1]))
  )
  const pruned = pruneExpired
    ? pruneRecords(validShares, Date.now(), preserveExpired)

View on GitHub (pinned to 1136503c6a)