thedotmack/claude-mem · error · Error

agent_event source_id must equal agent_event_id

Error message

agent_event source_id must equal agent_event_id

What it means

When sourceType is 'agent_event', the sourceId is required to be the agent event's ID: the resolved agentEventId (explicit agentEventId ?? sourceId) must equal input.sourceId. Passing a different value for sourceId and agentEventId is contradictory, so addSource throws before any database work.

Solutions

  1. Set sourceId to the agent event's id whenever sourceType is 'agent_event'.
  2. Omit agentEventId entirely (it defaults from sourceId) instead of passing a second id.
  3. If you intended a non-agent-event source, change sourceType to the matching type ('manual', 'session_summary', etc.).

Example fix

// before
await repo.addSource({ sourceType: 'agent_event', sourceId: sessionId, agentEventId: eventId, ... });
// after
await repo.addSource({ sourceType: 'agent_event', sourceId: eventId, ... });
Defensive patterns

Strategy: validation

Validate before calling

if (sourceType === 'agent_event' && sourceId !== (agentEventId ?? sourceId)) {
  throw new Error('agent_event addSource requires sourceId === agentEventId');
}

Type guard

function isConsistentAgentEventSource(input: { sourceType: string; sourceId: string; agentEventId?: string | null }): boolean {
  return input.sourceType !== 'agent_event' || (input.agentEventId ?? input.sourceId) === input.sourceId;
}

Try / catch

try {
  await repo.addSource(input);
} catch (e) {
  if (e instanceof Error && e.message === 'agent_event source_id must equal agent_event_id') {
    throw new Error(`bad addSource call: sourceId=${input.sourceId} agentEventId=${input.agentEventId}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling addSource with sourceType='agent_event' and both agentEventId and sourceId supplied where agentEventId !== sourceId; e.g. passing the observation id or a session id as sourceId while supplying the real event id in agentEventId.

Common situations: Copy-paste of a manual/session_summary addSource call changed to 'agent_event' without updating sourceId; wrappers that thread distinct ids into both fields; unit tests reusing fixtures from other source types.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/bbc4cf804be63a5f. Report an issue: GitHub.

Appendix: 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 d8bc9755e7)