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

  1. Resolve the observation via getByIdForScope before adding it as a reindex source.
  2. Confirm sourceId is the observation id (not a source row id or job id).
  3. 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

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


AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12). Data as JSON: /api/errors/ca3b1e9dc4b55c05. Report an issue: GitHub.