paperclipai/paperclip · warning · SetupTokenSessionError
Too many active setup-token login sessions.
Error message
Too many active setup-token login sessions.
What it means
Capacity rejection from SetupTokenSessionService.start: the per-slot (per-owner) cap is enforced synchronously in reserveCapacity — a slot is the company + owner + adapter triple, and when reservedBySlot for that slot already equals caps.perOwner, the start fails closed with SetupTokenSessionError 429 SETUP_TOKEN_CAP_EXCEEDED ("Too many active setup-token login sessions.", server/src/services/setup-token-session.ts:799). The reservation happens before any await, so concurrent starts cannot both squeeze through; a rejected start increments nothing.
Source
Thrown at server/src/services/setup-token-session.ts:836
private static decrementCount(counts: Map<string, number>, key: string): void {
const next = (counts.get(key) ?? 0) - 1;
if (next > 0) {
counts.set(key, next);
} else {
counts.delete(key);
}
}
/** Builds the company, owner, and adapter slot key. The reservation and the
* database active-slot unique index share this identity. */
private static slotKey(
scope: Pick<SetupTokenSessionScope, "companyId" | "ownerUserId" | "adapterType">,
): string {
return [scope.companyId, scope.ownerUserId, scope.adapterType].join("\u0000");
}
/**
* Reserves the capacity for one start under every enforced cap. The method is
* synchronous, so it runs to completion before the first `await` in
* {@link start}. Two concurrent starts for one slot cannot interleave inside
* it: the first reserves the slot, and the second reads the incremented count
* and fails closed with the fixed 429 cap error. The method holds the per-slot
* and per-company semantics; the slot is the company, the owner, and the
* adapter. It increments no counter on a rejection, so a rejected start
* reserves nothing.
*/
private reserveCapacity(scope: SetupTokenSessionScope): CapReservation {
const slotKey = SetupTokenSessionService.slotKey(scope);
if ((this.reservedBySlot.get(slotKey) ?? 0) >= this.caps.perOwner) {
throw new SetupTokenSessionError(429, SETUP_TOKEN_CAP_EXCEEDED);
}
if ((this.reservedByCompany.get(scope.companyId) ?? 0) >= this.caps.perCompany) {
throw new SetupTokenSessionError(429, SETUP_TOKEN_CAP_EXCEEDED);
}
SetupTokenSessionService.incrementCount(this.reservedBySlot, slotKey);View on GitHub (pinned to 01ad858492)
Solutions
- List the owner's active setup-token sessions and cancel/expire the stale ones (abort or wait for TTL) before starting a new one.
- Fix client retry loops to reuse the existing session (same sessionId) instead of starting a new login on each attempt.
- Wait for the TTL to reap lingering sessions if no cancel API is available.
- If the workload legitimately needs more concurrent logins per owner, raise caps.perOwner in service configuration.
Defensive patterns
Strategy: retry
Validate before calling
const active = await setupTokenSessions.listActive({ companyId, ownerUserId, adapterType });
if (active.length >= PER_OWNER_CAP) { await setupTokenSessions.cancel(active[0].sessionId); } // free one slot before start Try / catch
try { return await svc.start(scope); } catch (err) { if (err instanceof SetupTokenSessionError && err.status === 429) { await cancelOldestActiveSession(scope); return await svc.start(scope); } throw err; } Prevention
- Reuse the existing sessionId on retry instead of starting a new login session.
- Cancel abandoned login sessions promptly so per-owner slots free up before TTL expiry.
- Keep only one in-flight setup-token login per owner+adapter in UI flows.
When it happens
Trigger: Calling start(scope) for a company/owner/adapter combination that already has caps.perOwner active setup-token login sessions — e.g. the same user starts repeated OAuth setup-token logins for the same adapter without letting earlier sessions expire (TTL) or reach a terminal state.
Common situations: Retry loops hammering the login-start endpoint after a slow adapter; multiple browser tabs each starting a login; tests that start sessions without terminating them; sessions lingering because the login process never completes and the TTL is long.
Related errors
- The setup-token login session could not start.
- dropping batch ${batch.batchId} after ${batch.attempt} attem
- Anthropic Managed Agents request failed with HTTP ${response
- The bridge host reached its reserved process body byte ceili
- The bridge host reached its reserved process body byte ceili
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-08-21).
Data as JSON: /api/errors/e50113a6bc558faa.
Report an issue: GitHub.