{"record":{"id":"bbc4cf804be63a5f","repo":"thedotmack/claude-mem","slug":"agent-event-source-id-must-equal-agent-event-id","errorCode":null,"errorMessage":"agent_event source_id must equal agent_event_id","messagePattern":"agent_event source_id must equal agent_event_id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/storage/postgres/observations.ts","lineNumber":228,"sourceCode":"    generationJobId?: string | null;\n    metadata?: JsonObject;\n  }): Promise<PostgresObservationSource> {\n    const observation = await queryOne<{ id: string }>(\n      this.client,\n      'SELECT id FROM observations WHERE id = $1 AND project_id = $2 AND team_id = $3',\n      [input.observationId, input.projectId, input.teamId]\n    );\n    if (!observation) {\n      throw new Error('observation_id does not exist');\n    }\n\n    const agentEventId = input.sourceType === 'agent_event'\n      ? input.agentEventId ?? input.sourceId\n      : null;\n\n    if (input.sourceType === 'agent_event') {\n      if (agentEventId !== input.sourceId) {\n        throw new Error('agent_event source_id must equal agent_event_id');\n      }\n      await assertAgentEventOwnership(this.client, input.sourceId, input.projectId, input.teamId);\n    } else if (input.sourceType === 'session_summary' && !input.generationJobId) {\n      await assertSessionOwnership(this.client, input.sourceId, input.projectId, input.teamId);\n    } else if (input.sourceType === 'observation_reindex' && !input.generationJobId) {\n      await assertObservationOwnership(this.client, input.sourceId, input.projectId, input.teamId);\n    }\n    if (input.generationJobId) {\n      await assertGenerationJobMatchesSource(this.client, {\n        generationJobId: input.generationJobId,\n        projectId: input.projectId,\n        teamId: input.teamId,\n        sourceType: input.sourceType,\n        sourceId: input.sourceId,\n        agentEventId\n      });\n    }\n","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/storage/postgres/observations.ts#L210-L246","documentation":"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.","triggerScenarios":"Calling addSource() with sourceType:'agent_event' where agentEventId is set and agentEventId !== sourceId. The check runs before assertAgentEventOwnership.","commonSituations":"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.","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."],"exampleFix":"// before\nawait sources.addSource({ observationId, projectId, teamId, sourceType:'agent_event', sourceId: eventId, agentEventId: otherEventId });\n// after\nawait sources.addSource({ observationId, projectId, teamId, sourceType:'agent_event', sourceId: eventId, agentEventId: eventId });","handlingStrategy":"validation","validationCode":"if (sourceType==='agent_event') { const id = agentEventId ?? sourceId; if (agentEventId != null && agentEventId !== sourceId) throw new TypeError('agent_event sourceId must equal agentEventId'); }","typeGuard":"function isAgentEventSourceConsistent(input){ if (input.sourceType!=='agent_event') return true; return input.agentEventId == null || input.agentEventId === input.sourceId; }","tryCatchPattern":null,"preventionTips":["For agent_event, treat sourceId and agentEventId as the same field."],"tags":["postgres","validation","observations","invariant"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}