{"record":{"id":"16b28054261e4f1f","repo":"musistudio/claude-code-router","slug":"media-job-not-found-id-16b280","errorCode":null,"errorMessage":"Media job not found: ${id}","messagePattern":"Media job not found: (.+?)","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/media/storage.ts","lineNumber":43,"sourceCode":"  get(id: string): MediaJob | undefined {\n    const job = this.jobs.get(id);\n    return job ? structuredClone(job) : undefined;\n  }\n\n  list(): MediaJob[] {\n    return [...this.jobs.values()].map((job) => structuredClone(job));\n  }\n\n  put(job: MediaJob): MediaJob {\n    this.jobs.set(job.id, structuredClone(job));\n    this.flush();\n    return structuredClone(job);\n  }\n\n  update(id: string, patch: Partial<MediaJob>): MediaJob {\n    const current = this.jobs.get(id);\n    if (!current) {\n      throw new Error(`Media job not found: ${id}`);\n    }\n    const next: MediaJob = {\n      ...current,\n      ...patch,\n      id: current.id,\n      updatedAt: new Date().toISOString()\n    };\n    this.jobs.set(id, next);\n    this.flush();\n    return structuredClone(next);\n  }\n\n  deleteOlderThan(cutoffMs: number): MediaJob[] {\n    const deleted: MediaJob[] = [];\n    for (const [id, job] of this.jobs) {\n      const timestamp = Date.parse(job.finishedAt ?? job.updatedAt);\n      if ([\"canceled\", \"failed\", \"succeeded\"].includes(job.status) && Number.isFinite(timestamp) && timestamp < cutoffMs) {\n        this.jobs.delete(id);","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/media/storage.ts#L25-L61","documentation":"MediaJobStore.update refuses to patch an id that is not in the underlying Map, keeping records immutable-by-replacement. Any workflow that updates a job after it was deleted (retention cleanup) or in a different store instance hits this.","triggerScenarios":"Calling update() with an unknown id — e.g. the job aged out via deleteOlderThan between read and update, or the store was recreated (restart) and ids no longer exist.","commonSituations":"Race between long-running job completion and retention cleanup; in-memory store not shared across processes after a restart.","solutions":["Re-check existence immediately before update and skip/ignore if gone","Increase jobRetentionDays so active jobs can't be pruned mid-flight","Ensure updates happen on the same store instance that created the job"],"exampleFix":"// before\nstore.update(job.id, patch);\n// after\nconst current = store.get(job.id);\nif (current) store.update(job.id, patch);","handlingStrategy":"try-catch","validationCode":"if (!jobStore.get(id)) return; // job already gone","typeGuard":"const isLiveJob = (id: string, store: MediaJobStore): boolean => Boolean(store.get(id));","tryCatchPattern":"try { jobStore.update(id, patch); } catch (e) { if (e instanceof Error && e.message.startsWith(\"Media job not found\")) return; throw e; }","preventionTips":["Increase job retention beyond longest job duration","Check-then-update on the same store instance"],"tags":["media","storage","race-condition"],"backgroundTag":"stale-resource-update","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}