{"record":{"id":"80e9ca635c9c51ad","repo":"can1357/oh-my-pi","slug":"archive-destination-exists-destsession","errorCode":null,"errorMessage":"archive destination exists: ${destSession}","messagePattern":"archive destination exists: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/cli/gc-cli.ts","lineNumber":526,"sourceCode":"\t\tif (renamed) await fs.rm(destination, { force: true });\n\t\tthrow error;\n\t}\n}\n\nasync function restoreGzipSessionFile(source: string, destination: string): Promise<void> {\n\tawait fs.mkdir(path.dirname(destination), { recursive: true });\n\tconst decompressed = gunzipSync(await Bun.file(source).bytes());\n\tawait Bun.write(destination, decompressed);\n\tawait fs.unlink(source);\n}\n\nasync function moveSessionWithArtifacts(candidate: ArchiveCandidate): Promise<void> {\n\tconst sourceSession = candidate.session.path;\n\tconst destSession = candidate.destinationPath;\n\tconst legacyDestSession = destSession.endsWith(\".gz\") ? destSession.slice(0, -\".gz\".length) : `${destSession}.gz`;\n\tconst sourceArtifacts = sessionArtifactsPath(sourceSession);\n\tconst destArtifacts = sessionArtifactsPath(destSession);\n\tif (await pathExists(destSession)) throw new Error(`archive destination exists: ${destSession}`);\n\tif (await pathExists(legacyDestSession)) throw new Error(`archive destination exists: ${legacyDestSession}`);\n\tif ((await pathExists(sourceArtifacts)) && (await pathExists(destArtifacts))) {\n\t\tthrow new Error(`archive artifacts destination exists: ${destArtifacts}`);\n\t}\n\n\tconst moved: Array<{ source: string; destination: string; compressed?: boolean }> = [];\n\ttry {\n\t\tawait gzipSessionFile(sourceSession, destSession);\n\t\tmoved.push({ source: sourceSession, destination: destSession, compressed: true });\n\t\tif (await pathExists(sourceArtifacts)) {\n\t\t\tawait movePath(sourceArtifacts, destArtifacts);\n\t\t\tmoved.push({ source: sourceArtifacts, destination: destArtifacts });\n\t\t}\n\t} catch (error) {\n\t\tfor (const move of moved.reverse()) {\n\t\t\ttry {\n\t\t\t\tif (move.compressed) {\n\t\t\t\t\tawait restoreGzipSessionFile(move.destination, move.source);","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/cli/gc-cli.ts#L508-L544","documentation":"moveSessionWithArtifacts archives a session file by gzipping it to a destination path. Before any move it checks that neither the destination nor its legacy (.gz-less or .gz-suffixed) counterpart exists, throwing this error to avoid silently overwriting an existing archive.","triggerScenarios":"Archiving a session when candidate.destinationPath already exists on disk — e.g. re-running GC after a previous partial archive, or two sessions resolving to the same destination name.","commonSituations":"Repeated `omp gc`/stats-cleanup runs where a prior run crashed after writing the destination; session files renamed/copied so their computed destination collides; concurrent GC invocations racing on the same session.","solutions":["Inspect the destination path in the message; delete or rename the stale archive if it is no longer needed, then re-run GC","Ensure only one GC process runs at a time (the GC lock should enforce this — check for stale locks)","If the collision is systematic, fix the destination-naming logic so archived sessions get unique destinations"],"exampleFix":"// before\nmv session.jsonl session.jsonl.gz  // fails if destination exists\n// after\nrm stale-session.jsonl.gz && omp gc  // clear stale archive, then retry","handlingStrategy":"validation","validationCode":"import * as fs from \"node:fs/promises\";\nconst dest = computeDestinationPath(sessionPath);\nfor (const p of [dest, dest.replace(/\\.gz$/, \"\")]) {\n  try { await fs.access(p); throw new Error(`destination exists: ${p}`); }\n  catch (e) { if ((e as NodeJS.ErrnoException).code !== \"ENOENT\") throw e; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await archiveSession(candidate);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"archive destination exists:\")) {\n    const dest = err.message.split(\"archive destination exists: \")[1];\n    // inspect/resolve the collision (delete stale archive or pick a new destination) before retrying\n  } else throw err;\n}","preventionTips":["Run only one GC at a time and respect the GC lock","Clean up after interrupted archive runs before re-running GC","Verify prior-run state (destinations already written) before retrying an archive batch"],"tags":["filesystem","archive","gc","collision"],"backgroundTag":"file-already-exists","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}