thedotmack/claude-mem · error

server_session_id must belong to project_id and team_id

Error message

server_session_id must belong to project_id and team_id

What it means

Thrown by assertSessionOwnership (shared helper in utils.ts). It queries server_sessions by (id, project_id, team_id); a missing row means the server session is not in the project/team scope. Used wherever a serverSessionId must be validated against tenant boundaries.

Source

Thrown at src/storage/postgres/utils.ts:78

  );
  if (!row) {
    throw new Error('project_id must belong to team_id');
  }
}

export async function assertSessionOwnership(
  client: PostgresQueryable,
  serverSessionId: string,
  projectId: string,
  teamId: string
): Promise<void> {
  const row = await queryOne<{ id: string }>(
    client,
    'SELECT id FROM server_sessions WHERE id = $1 AND project_id = $2 AND team_id = $3',
    [serverSessionId, projectId, teamId]
  );
  if (!row) {
    throw new Error('server_session_id must belong to project_id and team_id');
  }
}

export function canonicalJson(value: unknown): string {
  return JSON.stringify(sortJson(value));
}

export function deterministicKey(parts: readonly unknown[]): string {
  const fingerprint = createHash('sha256')
    .update(canonicalJson(parts))
    .digest('hex');
  return fingerprint;
}

function sortJson(value: unknown): unknown {
  if (Array.isArray(value)) {
    return value.map(sortJson);
  }

View on GitHub (pinned to d768ba3643)

Solutions

  1. Resolve the server session within scope before referencing it.
  2. Confirm the session was created under the same project/team.
  3. Use the id stored in server_sessions exactly.

Example fix

// before
await observations.create({ projectId, teamId, serverSessionId: staleId, content });
// after
const session = await serverSessions.getByIdForScope({ id: serverSessionId, projectId, teamId });
if (!session) throw new Error('session not in scope');
await observations.create({ projectId, teamId, serverSessionId, content });
Defensive patterns

Strategy: validation

Validate before calling

const session = await serverSessions.getByIdForScope({ id: serverSessionId, projectId, teamId });
if (!session) throw new Error('server_session not in scope');

Prevention

When it happens

Trigger: Passing a serverSessionId that does not exist under the given project/team to create()/validateSource() or any helper that calls assertSessionOwnership. Project ownership is usually validated separately first.

Common situations: Session id from another project/tenant, expired/purged session, stale cached id, or a derived session-group id being passed instead of the real server_session id.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12). Data as JSON: /api/errors/8a96bec8ab8a7a2f. Report an issue: GitHub.