{"record":{"id":"60b3a2e97a60c1f3","repo":"thedotmack/claude-mem","slug":"session-summary-source-id-must-equal-server-sessio","errorCode":null,"errorMessage":"session_summary source_id must equal server_session_id","messagePattern":"session_summary source_id must equal server_session_id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/storage/postgres/generation-jobs.ts","lineNumber":276,"sourceCode":"        [eventId, input.projectId, input.teamId]\n      );\n      if (!row || input.sourceId !== eventId) {\n        throw new Error('agent_event source_id must belong to project_id and team_id');\n      }\n      if (input.serverSessionId) {\n        await assertSessionOwnership(this.client, input.serverSessionId, input.projectId, input.teamId);\n        if (row.server_session_id && row.server_session_id !== input.serverSessionId) {\n          throw new Error('server_session_id must match the agent_event server_session_id');\n        }\n      }\n      return;\n    }\n\n    if (input.sourceType === 'session_summary') {\n      const sessionId = input.serverSessionId ?? input.sourceId;\n      await assertSessionOwnership(this.client, sessionId, input.projectId, input.teamId);\n      if (input.sourceId !== sessionId) {\n        throw new Error('session_summary source_id must equal server_session_id');\n      }\n      return;\n    }\n\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.sourceId, input.projectId, input.teamId]\n    );\n    if (!observation) {\n      throw new Error('observation_reindex source_id must belong to project_id and team_id');\n    }\n    if (input.serverSessionId) {\n      await assertSessionOwnership(this.client, input.serverSessionId, input.projectId, input.teamId);\n    }\n  }\n}\n","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/storage/postgres/generation-jobs.ts#L258-L294","documentation":"Thrown by validateSource when sourceType is 'session_summary'. The resolved sessionId is serverSessionId ?? sourceId; if the caller supplies both a sourceId and a serverSessionId that are not identical, the job is rejected. session_summary sources are keyed entirely by a single server session, so the two fields must collapse to the same value.","triggerScenarios":"Calling repository.create() with sourceType:'session_summary' where sourceId and serverSessionId are both set and differ. AssertSessionOwnership runs first, so both must exist in scope before this guard triggers.","commonSituations":"Orchestrator defaults serverSessionId to a global value while sourceId is the real session; UI passing a derived/session-group id as sourceId alongside the real session id; refactor that started populating both fields where only one was used before.","solutions":["Pass sourceId and serverSessionId as the same value (the canonical server session id).","Pass only sourceId (serverSessionId omitted); validateSource uses serverSessionId ?? sourceId so it resolves correctly.","Pass only serverSessionId and set sourceId to the same session id."],"exampleFix":"// before\nawait jobs.create({ sourceType:'session_summary', sourceId: groupId, serverSessionId: sessionId, ... });\n// after\nawait jobs.create({ sourceType:'session_summary', sourceId: sessionId, serverSessionId: sessionId, ... });","handlingStrategy":"validation","validationCode":"function normalizeSessionSummarySource(sourceId, serverSessionId) {\n  if (sourceId != null && serverSessionId != null && sourceId !== serverSessionId) {\n    throw new TypeError('sourceId and serverSessionId must be identical for session_summary');\n  }\n  const sessionId = serverSessionId ?? sourceId;\n  return { sourceId: sessionId, serverSessionId: sessionId };\n}","typeGuard":"function isSessionSummaryConsistent(input) {\n  if (input.sourceType !== 'session_summary') return true;\n  const both = input.sourceId != null && input.serverSessionId != null;\n  return !both || input.sourceId === input.serverSessionId;\n}","tryCatchPattern":null,"preventionTips":["For session_summary, treat sourceId and serverSessionId as one field; never pass two different values."],"tags":["postgres","validation","multi-tenant","generation-jobs"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}