{"record":{"id":"4528765b56feaf0b","repo":"thedotmack/claude-mem","slug":"observation-reindex-source-id-must-belong-to-proje","errorCode":null,"errorMessage":"observation_reindex source_id must belong to project_id and team_id","messagePattern":"observation_reindex source_id must belong to project_id and team_id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/storage/postgres/generation-jobs.ts","lineNumber":287,"sourceCode":"      return;\n    }\n\n    if (input.sourceType === 'session_summary') {\n      const sessionId = input.serverSessionId ?? input.sourceId;\n      await assertSessionOwnership(this.client, sessionId, input.projectId, input.teamId);\n      if (input.sourceId !== sessionId) {\n        throw new Error('session_summary source_id must equal server_session_id');\n      }\n      return;\n    }\n\n    const observation = await queryOne<{ id: string }>(\n      this.client,\n      'SELECT id FROM observations WHERE id = $1 AND project_id = $2 AND team_id = $3',\n      [input.sourceId, input.projectId, input.teamId]\n    );\n    if (!observation) {\n      throw new Error('observation_reindex source_id must belong to project_id and team_id');\n    }\n    if (input.serverSessionId) {\n      await assertSessionOwnership(this.client, input.serverSessionId, input.projectId, input.teamId);\n    }\n  }\n}\n\nexport class PostgresObservationGenerationJobEventsRepository {\n  constructor(private client: PostgresQueryable) {}\n\n  async append(input: {\n    id?: string;\n    generationJobId: string;\n    projectId: string;\n    teamId: string;\n    eventType: ObservationGenerationJobEventType;\n    statusAfter: ObservationGenerationJobStatus;\n    attempt?: number;","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/storage/postgres/generation-jobs.ts#L269-L305","documentation":"Thrown by validateSource when sourceType is 'observation_reindex'. The code looks up an observations row by (id=sourceId, project_id, team_id); if none exists the source observation is not accessible in that project/team scope, so the reindex job cannot be created.","triggerScenarios":"Calling repository.create() with sourceType:'observation_reindex' and a sourceId that is not a row in observations for the given project and team. Note: sourceType here is 'observation_reindex' in the job repo, which only allows three types; the observation must already exist.","commonSituations":"Reindexing an observation from the wrong project/team, using an observation id from another tenant, reindexing an observation that was deleted, or a typo/corrupted id after an export-import.","solutions":["Verify the observation exists in scope first: SELECT id FROM observations WHERE id=$1 AND project_id=$2 AND team_id=$3.","Confirm you are using the correct projectId and teamId for that observation (cross-tenant id reuse).","If the observation was deleted, recreate it or choose a different existing source."],"exampleFix":"// before\nawait jobs.create({ sourceType:'observation_reindex', sourceId: maybeDeletedId, projectId, teamId, jobType });\n// after\nconst obs = await observations.getByIdForScope({ id: sourceId, projectId, teamId });\nif (!obs) throw new Error('source observation not found in scope');\nawait jobs.create({ sourceType:'observation_reindex', sourceId, projectId, teamId, jobType });","handlingStrategy":"validation","validationCode":"const obs = await observations.getByIdForScope({ id: sourceId, projectId, teamId });\nif (!obs) throw new Error(`observation ${sourceId} not found in project ${projectId}/team ${teamId}`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Resolve observation through getByIdForScope before scheduling a reindex job.","Keep project/team ids threaded through every call site; never default them."],"tags":["postgres","validation","multi-tenant","ownership","generation-jobs"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}