thedotmack/claude-mem · error
observation_reindex source_id must belong to project_id and
Error message
observation_reindex source_id must belong to project_id and team_id
What it means
Thrown by assertObservationOwnership (private helper) when addSource is called with sourceType 'observation_reindex' and no generationJobId. It looks up observations by (id=sourceId, project_id, team_id); missing means the source observation is not in scope. The message reuses the 'observation_reindex source_id' wording to identify which field is wrong.
Source
Thrown at src/storage/postgres/observations.ts:388
);
if (!row) {
throw new Error('agent_event_id must belong to project_id and team_id');
}
}
async function assertObservationOwnership(
client: PostgresQueryable,
observationId: string,
projectId: string,
teamId: string
): Promise<void> {
const row = await queryOne<{ id: string }>(
client,
'SELECT id FROM observations WHERE id = $1 AND project_id = $2 AND team_id = $3',
[observationId, projectId, teamId]
);
if (!row) {
throw new Error('observation_reindex source_id must belong to project_id and team_id');
}
}
function mapObservationRow(row: ObservationRow): PostgresObservation {
return {
id: row.id,
projectId: row.project_id,
teamId: row.team_id,
serverSessionId: row.server_session_id,
kind: row.kind,
content: row.content,
generationKey: row.generation_key,
metadata: toJsonObject(row.metadata),
embedding: row.embedding,
createdByJobId: row.created_by_job_id,
createdAtEpoch: toEpoch(row.created_at),
updatedAtEpoch: toEpoch(row.updated_at)
};View on GitHub (pinned to d768ba3643)
Solutions
- Resolve the observation via getByIdForScope before adding it as a reindex source.
- Confirm sourceId is the observation id (not a source row id or job id).
- If the source was deleted, pick a current observation or recreate it.
Example fix
// before
await sources.addSource({ observationId, projectId, teamId, sourceType:'observation_reindex', sourceId: maybeSourceRowId });
// after
const src = await observations.getByIdForScope({ id: sourceId, projectId, teamId });
if (!src) throw new Error('source observation not in scope');
await sources.addSource({ observationId, projectId, teamId, sourceType:'observation_reindex', sourceId }); Defensive patterns
Strategy: validation
Validate before calling
const src = await observations.getByIdForScope({ id: sourceId, projectId, teamId });
if (!src) throw new Error('source observation not in scope'); Prevention
- Use the observation id, not the source-row id, when reindexing.
When it happens
Trigger: Calling addSource({sourceType:'observation_reindex', sourceId}) without a generationJobId, where sourceId is not an observation in the given project/team. (When a generationJobId is present, this branch is skipped in favor of assertGenerationJobMatchesSource.)
Common situations: Reindexing an observation from the wrong tenant; deleted source observation; passing an observation_source id instead of the observation id.
Related errors
- observation_id does not exist
- generation_job_id must belong to project_id and team_id
- agent_event_id must belong to project_id and team_id
- server_session_id must match the agent_event server_session_
- observation_reindex source_id must belong to project_id and
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/ca3b1e9dc4b55c05.
Report an issue: GitHub.