thedotmack/claude-mem · error
generation_job_id source model must match observation source
Error message
generation_job_id source model must match observation source
What it means
Thrown by assertGenerationJobMatchesSource after confirming the job exists in scope. It compares the job's stored source_type and source_id against the sourceType/sourceId supplied to addSource. A mismatch means the observation's source does not match the source the job was created from, so they cannot be linked.
Source
Thrown at src/storage/postgres/observations.ts:353
const row = await queryOne<{
id: string;
source_type: string;
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) {View on GitHub (pinned to d768ba3643)
Solutions
- Look up the job and use its source_type/source_id as the source for the observation.
- Create a dedicated job for the exact (sourceType, sourceId) before linking.
- Do not share one job id across different sources.
Example fix
// before
await sources.addSource({ observationId, projectId, teamId, sourceType:'session_summary', sourceId: sessionId, generationJobId: agentEventJobId });
// after
const job = await jobs.getByIdForScope({ id: generationJobId, projectId, teamId });
await sources.addSource({ observationId, projectId, teamId, sourceType: job.sourceType, sourceId: job.sourceId, generationJobId: job.id }); Defensive patterns
Strategy: validation
Validate before calling
const job = await jobs.getByIdForScope({ id: generationJobId, projectId, teamId });
if (job.sourceType !== sourceType || job.sourceId !== sourceId) throw new Error('source/job mismatch'); Type guard
function jobMatchesSource(job, input){ return job.sourceType===input.sourceType && job.sourceId===input.sourceId; } Prevention
- One job per (sourceType, sourceId); never reuse across sources.
When it happens
Trigger: addSource with a generationJobId where the job's (source_type, source_id) differ from the (sourceType, sourceId) passed in. E.g. job created from agent_event X but you try to link a session_summary source.
Common situations: Mixing up jobs for different sources; reusing a job id across reprocessed sources; UI passing a default job id regardless of which source is being linked.
Related errors
- agent_event source_id must equal agent_event_id
- manual observation sources cannot be linked to a generation_
- generation_job_id agent_event_id must match observation sour
- observation_id does not exist
- generation_job_id must belong to project_id and team_id
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/62705560e62eaa79.
Report an issue: GitHub.