thedotmack/claude-mem · error · Error

session_summary source_id must equal server_session_id

Error message

session_summary source_id must equal server_session_id

What it means

For sourceType 'session_summary', validateSource requires that sourceId equals the effective session id (input.serverSessionId if given, otherwise sourceId itself), and that session ownership over project/team is asserted. Thrown when the caller supplies a sourceId that does not match the server_session_id being used.

Solutions

  1. Set sourceId to the server session id the summary belongs to
  2. Remove the separate serverSessionId field or make it identical to sourceId
  3. Verify the session exists under the same project_id and team_id via an ownership check before calling
  4. Regenerate the summary if the original session was deleted

Example fix

// before
await jobs.create({ sourceType: 'session_summary', sourceId: summaryId, serverSessionId: sessionId });
// after
await jobs.create({ sourceType: 'session_summary', sourceId: sessionId, serverSessionId: sessionId });
Defensive patterns

Strategy: validation

Validate before calling

if (input.sourceType === 'session_summary' && input.serverSessionId && input.sourceId !== input.serverSessionId) {
  throw new Error('session_summary sourceId must equal serverSessionId');
}

Try / catch

try {
  await jobs.create(input);
} catch (err) {
  if (err instanceof Error && err.message.includes('session_summary source_id must equal')) {
    await jobs.create({ ...input, sourceId: input.serverSessionId ?? input.sourceId });
  } else throw err;
}

Prevention

When it happens

Trigger: create() with sourceType 'session_summary' where sourceId !== (serverSessionId ?? sourceId) — i.e. both serverSessionId and sourceId are set and differ, or sourceId is not a valid server session id owned by the project/team.

Common situations: Caller passes an observation or summary id as sourceId instead of the session id; copying serverSessionId from a different conversation; typos or truncated session uuids in API payloads.

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/60b3a2e97a60c1f3. Report an issue: GitHub.

Appendix: source

Thrown at src/storage/postgres/generation-jobs.ts:285

        [eventId, input.projectId, input.teamId]
      );
      if (!row || input.sourceId !== eventId) {
        throw new Error('agent_event source_id must belong to project_id and team_id');
      }
      if (input.serverSessionId) {
        await assertSessionOwnership(this.client, input.serverSessionId, input.projectId, input.teamId);
        if (row.server_session_id && row.server_session_id !== input.serverSessionId) {
          throw new Error('server_session_id must match the agent_event server_session_id');
        }
      }
      return;
    }

    if (input.sourceType === 'session_summary') {
      const sessionId = input.serverSessionId ?? input.sourceId;
      await assertSessionOwnership(this.client, sessionId, input.projectId, input.teamId);
      if (input.sourceId !== sessionId) {
        throw new Error('session_summary source_id must equal server_session_id');
      }
      return;
    }

    const observation = await queryOne<{ id: string }>(
      this.client,
      'SELECT id FROM observations WHERE id = $1 AND project_id = $2 AND team_id = $3',
      [input.sourceId, input.projectId, input.teamId]
    );
    if (!observation) {
      throw new Error('observation_reindex source_id must belong to project_id and team_id');
    }
    if (input.serverSessionId) {
      await assertSessionOwnership(this.client, input.serverSessionId, input.projectId, input.teamId);
    }
  }
}

View on GitHub (pinned to d8bc9755e7)