thedotmack/claude-mem · error

observation_id does not exist

Error message

observation_id does not exist

What it means

Thrown by PostgresObservationSourcesRepository.addSource. It first checks that the target observation exists within (observationId, projectId, teamId). If no row is returned, the observation you are trying to attach a source to is not in scope (missing, wrong tenant, or deleted).

Source

Thrown at src/storage/postgres/observations.ts:219

  async addSource(input: {
    id?: string;
    observationId: string;
    projectId: string;
    teamId: string;
    sourceType: ObservationSourceType;
    sourceId: string;
    agentEventId?: string | null;
    generationJobId?: string | null;
    metadata?: JsonObject;
  }): Promise<PostgresObservationSource> {
    const observation = await queryOne<{ id: string }>(
      this.client,
      'SELECT id FROM observations WHERE id = $1 AND project_id = $2 AND team_id = $3',
      [input.observationId, input.projectId, input.teamId]
    );
    if (!observation) {
      throw new Error('observation_id does not exist');
    }

    const agentEventId = input.sourceType === 'agent_event'
      ? input.agentEventId ?? input.sourceId
      : null;

    if (input.sourceType === 'agent_event') {
      if (agentEventId !== input.sourceId) {
        throw new Error('agent_event source_id must equal agent_event_id');
      }
      await assertAgentEventOwnership(this.client, input.sourceId, input.projectId, input.teamId);
    } else if (input.sourceType === 'session_summary' && !input.generationJobId) {
      await assertSessionOwnership(this.client, input.sourceId, input.projectId, input.teamId);
    } else if (input.sourceType === 'observation_reindex' && !input.generationJobId) {
      await assertObservationOwnership(this.client, input.sourceId, input.projectId, input.teamId);
    }
    if (input.generationJobId) {
      await assertGenerationJobMatchesSource(this.client, {

View on GitHub (pinned to d768ba3643)

Solutions

  1. Create the observation first (repository.create on PostgresObservationRepository) and use its returned id.
  2. Resolve the observation via getByIdForScope before calling addSource; fail fast with a clearer message.
  3. Confirm projectId/teamId match the observation's owner tenant.

Example fix

// before
await sources.addSource({ observationId, projectId, teamId, sourceType:'agent_event', sourceId: eventId });
// after
const obs = await observations.create({ projectId, teamId, content, ... });
await sources.addSource({ observationId: obs.id, projectId, teamId, sourceType:'agent_event', sourceId: eventId });
Defensive patterns

Strategy: validation

Validate before calling

const obs = await observations.getByIdForScope({ id: observationId, projectId, teamId });
if (!obs) throw new Error(`observation ${observationId} not in scope`);

Prevention

When it happens

Trigger: Calling addSource() with an observationId that is not present in observations for the supplied project/team. The observation may belong to another tenant or may have never been created.

Common situations: Adding a source before creating the observation; cross-tenant id reuse; observation deleted by a cleanup job; using a source id instead of an observation id.

Related errors


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