thedotmack/claude-mem · error

generation_job_id agent_event_id must match observation sour

Error message

generation_job_id agent_event_id must match observation source

What it means

Thrown by assertGenerationJobMatchesSource for agent_event sources after the source_type/source_id match. It additionally checks that the job's agent_event_id equals the observation source's agentEventId. Even when both point to the same event, a divergent agent_event_id on either side rejects the link.

Source

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

    source_id: string;
    agent_event_id: string | null;
  }>(
    client,
    `
      SELECT id, source_type, source_id, agent_event_id
      FROM observation_generation_jobs
      WHERE id = $1 AND project_id = $2 AND team_id = $3
    `,
    [input.generationJobId, input.projectId, input.teamId]
  );
  if (!row) {
    throw new Error('generation_job_id must belong to project_id and team_id');
  }
  if (row.source_type !== input.sourceType || row.source_id !== input.sourceId) {
    throw new Error('generation_job_id source model must match observation source');
  }
  if (input.sourceType === 'agent_event' && row.agent_event_id !== input.agentEventId) {
    throw new Error('generation_job_id agent_event_id must match observation source');
  }
}

async function assertAgentEventOwnership(
  client: PostgresQueryable,
  agentEventId: string,
  projectId: string,
  teamId: string
): Promise<void> {
  const row = await queryOne<{ id: string }>(
    client,
    'SELECT id FROM agent_events WHERE id = $1 AND project_id = $2 AND team_id = $3',
    [agentEventId, projectId, teamId]
  );
  if (!row) {
    throw new Error('agent_event_id must belong to project_id and team_id');
  }
}

View on GitHub (pinned to d768ba3643)

Solutions

  1. Ensure agentEventId passed to addSource equals the job's agent_event_id (read it from the job).
  2. For agent_event, set sourceId === agentEventId === job.agentEventId.
  3. Recreate the job from the correct event if they truly differ.

Example fix

// before
await sources.addSource({ observationId, projectId, teamId, sourceType:'agent_event', sourceId: eventId, agentEventId: otherId, generationJobId });
// after
const job = await jobs.getByIdForScope({ id: generationJobId, projectId, teamId });
await sources.addSource({ observationId, projectId, teamId, sourceType:'agent_event', sourceId: job.agentEventId!, agentEventId: job.agentEventId, generationJobId: job.id });
Defensive patterns

Strategy: validation

Validate before calling

const job = await jobs.getByIdForScope({ id: generationJobId, projectId, teamId });
if (sourceType==='agent_event' && job.agentEventId !== (agentEventId ?? sourceId)) throw new Error('agent_event_id mismatch with job');

Type guard

function agentEventJobConsistent(job, input){ return job.sourceType!=='agent_event' || job.agentEventId === (input.agentEventId ?? input.sourceId); }

Prevention

When it happens

Trigger: addSource with sourceType 'agent_event', a generationJobId, where the job's stored agent_event_id != the resolved agentEventId (agentEventId ?? sourceId) of the observation source.

Common situations: Job created from one event but the observation source references a different event id; passing sourceId without agentEventId while the job stored a distinct agent_event_id.

Related errors


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