{"record":{"id":"1c013080a8e30520","repo":"can1357/oh-my-pi","slug":"archive-artifacts-destination-exists-destartifa","errorCode":null,"errorMessage":"archive artifacts destination exists: ${destArtifacts}","messagePattern":"archive artifacts destination exists: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/cli/gc-cli.ts","lineNumber":529,"sourceCode":"}\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);\n\t\t\t\t} else {\n\t\t\t\t\tawait movePath(move.destination, move.source);\n\t\t\t\t}","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/cli/gc-cli.ts#L511-L547","documentation":"When both the source session has an artifacts directory and the destination artifacts path already exists, the move is refused with this error — archiving would merge or overwrite artifact data that already occupies the target location.","triggerScenarios":"Archiving a session whose artifacts directory exists while a destination artifacts directory also exists — e.g. the session was partially archived before, or two sessions share an artifacts location.","commonSituations":"Partial archive from a crashed earlier run (session file moved back but artifacts left); duplicate session ids after copy/import; concurrent GC processes targeting the same destination.","solutions":["Inspect destArtifacts in the message; remove or relocate the stale destination artifacts directory if unneeded","Verify whether the artifacts belong to the same session (compare contents/ids) before deleting","Re-run GC once the destination artifacts path is clear"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import * as fs from \"node:fs/promises\";\nconst artifacts = sessionArtifactsPath(dest);\ntry { await fs.access(artifacts); throw new Error(`artifacts destination exists: ${artifacts}`); }\ncatch (e) { if ((e as NodeJS.ErrnoException).code !== \"ENOENT\") throw e; }","typeGuard":null,"tryCatchPattern":"try {\n  await archiveSession(candidate);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"archive artifacts destination exists:\")) {\n    const destArtifacts = err.message.split(\"exists: \")[1];\n    // compare/remove the stale destination artifacts directory, then retry\n  } else throw err;\n}","preventionTips":["Archive each session exactly once; avoid re-running archives on already-archived sessions","Clean up artifacts left by interrupted archive runs before retrying","Avoid copying/importing sessions in ways that duplicate artifacts paths"],"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"}