{"record":{"id":"ca3b1e9dc4b55c05","repo":"thedotmack/claude-mem","slug":"observation-reindex-source-id-must-belong-to-proje-ca3b1e","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":"Error","httpStatus":null,"severity":"error","filePath":"src/storage/postgres/observations.ts","lineNumber":388,"sourceCode":"  );\n  if (!row) {\n    throw new Error('agent_event_id must belong to project_id and team_id');\n  }\n}\n\nasync function assertObservationOwnership(\n  client: PostgresQueryable,\n  observationId: string,\n  projectId: string,\n  teamId: string\n): Promise<void> {\n  const row = await queryOne<{ id: string }>(\n    client,\n    'SELECT id FROM observations WHERE id = $1 AND project_id = $2 AND team_id = $3',\n    [observationId, projectId, teamId]\n  );\n  if (!row) {\n    throw new Error('observation_reindex source_id must belong to project_id and team_id');\n  }\n}\n\nfunction mapObservationRow(row: ObservationRow): PostgresObservation {\n  return {\n    id: row.id,\n    projectId: row.project_id,\n    teamId: row.team_id,\n    serverSessionId: row.server_session_id,\n    kind: row.kind,\n    content: row.content,\n    generationKey: row.generation_key,\n    metadata: toJsonObject(row.metadata),\n    embedding: row.embedding,\n    createdByJobId: row.created_by_job_id,\n    createdAtEpoch: toEpoch(row.created_at),\n    updatedAtEpoch: toEpoch(row.updated_at)\n  };","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/storage/postgres/observations.ts#L370-L406","documentation":"For 'observation_reindex' sources without a generationJobId, assertObservationOwnership verifies the sourceId refers to an existing observation row in the same project and team. The id is expected to point at an observations row; if it does not, reindex provenance cannot be established and the error is thrown.","triggerScenarios":"addSource with sourceType='observation_reindex', no generationJobId, and sourceId set to an id that is not an observations row in scope (a session id, an agent event id, a deleted observation, or wrong tenant).","commonSituations":"Reindex jobs that pass the wrong id field; observations deleted between listing and reindexing; running the reindex against a different database than the one the ids came from.","solutions":["Confirm sourceId is an observations id visible with the given projectId/teamId.","Re-create the observation if it was deleted, or skip reindexing it.","Ensure the reindex job reads ids and tenant ids from the same database it writes to."],"exampleFix":"// before\nawait repo.addSource({ sourceType: 'observation_reindex', sourceId: sessionId, ... });\n// after\nawait repo.addSource({ sourceType: 'observation_reindex', sourceId: observation.id, ... });","handlingStrategy":"validation","validationCode":"if (sourceType === 'observation_reindex' && !generationJobId) {\n  const ok = await db.oneOrNone(\n    'SELECT 1 FROM observations WHERE id = $1 AND project_id = $2 AND team_id = $3',\n    [sourceId, projectId, teamId]\n  );\n  if (!ok) throw new Error(`reindex source ${sourceId} is not an in-scope observation`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await repo.addSource(input);\n} catch (e) {\n  if (e instanceof Error && e.message === 'observation_reindex source_id must belong to project_id and team_id') {\n    logger.warn('skipping reindex of missing observation', { id: input.sourceId });\n    return null;\n  }\n  throw e;\n}","preventionTips":["For reindex sources, sourceId must be an observations id — double-check the field you pass.","Re-list observations and reindex in the same run so ids cannot go stale.","Run reindex jobs against the same database the ids were read from."],"tags":["postgres","reindex","tenant-scope"],"backgroundTag":"record-not-found","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}