thedotmack/claude-mem · error
agent_event source_id must equal agent_event_id
Error message
agent_event source_id must equal agent_event_id
What it means
Thrown by addSource when sourceType is 'agent_event'. The resolved agentEventId is (agentEventId ?? sourceId). If the caller also passed an explicit agentEventId that differs from sourceId, the invariant (sourceId === agentEventId for agent_event sources) is violated and the call is rejected before any DB ownership check.
Source
Thrown at src/storage/postgres/observations.ts:228
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, {
generationJobId: input.generationJobId,
projectId: input.projectId,
teamId: input.teamId,
sourceType: input.sourceType,
sourceId: input.sourceId,
agentEventId
});
}
View on GitHub (pinned to d768ba3643)
Solutions
- For agent_event sources, pass agentEventId and sourceId as the same value (or omit agentEventId so it defaults to sourceId).
- Decide on one canonical event id field and thread only that.
Example fix
// before
await sources.addSource({ observationId, projectId, teamId, sourceType:'agent_event', sourceId: eventId, agentEventId: otherEventId });
// after
await sources.addSource({ observationId, projectId, teamId, sourceType:'agent_event', sourceId: eventId, agentEventId: eventId }); Defensive patterns
Strategy: validation
Validate before calling
if (sourceType==='agent_event') { const id = agentEventId ?? sourceId; if (agentEventId != null && agentEventId !== sourceId) throw new TypeError('agent_event sourceId must equal agentEventId'); } Type guard
function isAgentEventSourceConsistent(input){ if (input.sourceType!=='agent_event') return true; return input.agentEventId == null || input.agentEventId === input.sourceId; } Prevention
- For agent_event, treat sourceId and agentEventId as the same field.
When it happens
Trigger: Calling addSource() with sourceType:'agent_event' where agentEventId is set and agentEventId !== sourceId. The check runs before assertAgentEventOwnership.
Common situations: Caller setting agentEventId to a different event than sourceId; refactor that started populating agentEventId explicitly without mirroring it into sourceId; confusion about which id is canonical.
Related errors
- manual observation sources cannot be linked to a generation_
- generation_job_id source model must match observation source
- 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/bbc4cf804be63a5f.
Report an issue: GitHub.