{"record":{"id":"fddf84387eddd79c","repo":"stablyai/orca","slug":"artifact-share-records-could-not-be-read-safely","errorCode":null,"errorMessage":"Artifact share records could not be read safely.","messagePattern":"Artifact share records could not be read safely\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/artifacts/artifact-share-record-store.ts","lineNumber":116,"sourceCode":"    changed: retained.length !== currentEntries.length\n  }\n}\n\nfunction readRecords(\n  profileId: string,\n  userDataPath: string,\n  preserveExpired?: { sourceKey: string; slug: string; editToken: string },\n  pruneExpired = true\n): ArtifactShareRecordFile {\n  const path = recordPath(profileId, userDataPath)\n  if (!existsSync(path)) {\n    return { version: 2, lifecycleGeneration: 0, lifecycleNonce: '', shares: {} }\n  }\n  let parsed: ParsedArtifactShareRecordFile\n  try {\n    parsed = JSON.parse(readFileSync(path, 'utf8')) as ParsedArtifactShareRecordFile\n  } catch (error) {\n    throw new Error('Artifact share records could not be read safely.', { cause: error })\n  }\n  if (parsed.version === 1) {\n    return { version: 2, lifecycleGeneration: 0, lifecycleNonce: '', shares: {} }\n  }\n  if (\n    parsed.version !== 2 ||\n    !parsed.shares ||\n    typeof parsed.shares !== 'object' ||\n    Array.isArray(parsed.shares)\n  ) {\n    throw new Error('Artifact share records have an unsupported format.')\n  }\n  const shareEntries = Object.entries(parsed.shares as Record<string, unknown>)\n  const validShares = Object.fromEntries(\n    shareEntries.filter((entry): entry is [string, ArtifactShareRecord] => isRecord(entry[1]))\n  )\n  const pruned = pruneExpired\n    ? pruneRecords(validShares, Date.now(), preserveExpired)","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/artifacts/artifact-share-record-store.ts#L98-L134","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read error.cause for the JSON parse offset and inspect the file around that byte.","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.","Ensure the writer uses atomic write-temp-then-rename so concurrent writes/crashes cannot corrupt the file."],"exampleFix":"// before\nconst records = readShareRecords(...) // JSON.parse throws\n\n// after\ntry { return readShareRecords(...) }\ncatch (e) {\n  if (e.cause instanceof SyntaxError) await restoreFromBackupOrReset(profileId, userDataPath)\n  throw\n}","handlingStrategy":"try-catch","validationCode":"import { readFileSync } from 'node:fs'\n\nfunction isShareRecordJsonParseable(path: string): boolean {\n  try { JSON.parse(readFileSync(path, 'utf8')); return true } catch { return false }\n}\n\nif (existsSync(path) && !isShareRecordJsonParseable(path)) {\n  await fs.promises.rename(path, `${path}.corrupt`)\n}","typeGuard":"function isJsonParseError(e: unknown): boolean {\n  return e instanceof SyntaxError || (e instanceof Error && e.cause instanceof SyntaxError)\n}","tryCatchPattern":"try {\n  return readShareRecords(profileId, userDataPath)\n} catch (e) {\n  if (isJsonParseError(e)) {\n    await backupAndResetShareRecords(profileId, userDataPath)\n    return { version: 2, lifecycleGeneration: 0, lifecycleNonce: '', shares: {} }\n  }\n  throw e\n}","preventionTips":["Ensure the share-record writer is atomic (temp + rename) so crashes cannot truncate it.","Disable sync/backup tools that rewrite the share-record file mid-write.","Run a parse-check on startup and quarantine corrupt files before they crash share operations."],"tags":["artifacts","share-record","json","corruption","filesystem"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}