ruvnet/ruflo · warning · ClaimOperationError
MAX_CLAIMS_EXCEEDED
MAX_CLAIMS_EXCEEDED
Error message
Cannot accept handoff: claimant ${claimant.name} at max capacity What it means
Thrown by acceptHandoff after the claim and pending handoff are validated, when the accepting claimant's active claim count (claimRepository.countByClaimant) is greater than or equal to claimant.maxConcurrentClaims, defaulting to 5 when unset. This is the capacity guard that prevents an agent from over-committing.
Source
Thrown at v3/@claude-flow/claims/src/application/claim-service.ts:380
}
// Find pending handoff for this claimant
const pendingHandoff = claim.handoffChain?.find(
(h) => h.status === 'pending' && h.to.id === claimant.id
);
if (!pendingHandoff) {
throw new ClaimOperationError(
'HANDOFF_NOT_FOUND',
`No pending handoff found for claimant ${claimant.name}`
);
}
// Check claimant's workload
const currentClaimCount = await this.claimRepository.countByClaimant(claimant.id);
const maxClaims = claimant.maxConcurrentClaims ?? 5;
if (currentClaimCount >= maxClaims) {
throw new ClaimOperationError(
'MAX_CLAIMS_EXCEEDED',
`Cannot accept handoff: claimant ${claimant.name} at max capacity`
);
}
// Update handoff record
pendingHandoff.status = 'accepted';
pendingHandoff.resolvedAt = new Date();
// Transfer claim to new owner
const previousClaimant = claim.claimant;
claim.claimant = claimant;
claim.status = 'active';
claim.lastActivityAt = new Date();
await this.claimRepository.save(claim);
// Emit eventsView on GitHub (pinned to 6b01dc5a68)
Solutions
- Release or complete existing claims on the accepting agent before retrying the accept.
- Set claimant.maxConcurrentClaims explicitly to a value that reflects the agent's real capacity.
- Have the load balancer re-route the handoff target via getSwarmLoad to a less-loaded agent.
- Retry the accept after a short delay during transient load spikes.
Example fix
// before
const claimant = { id: 'agent-1', type: 'agent', name: 'worker-1' };
await claimService.acceptHandoff(issueId, claimant); // at capacity
// after
const claimant = { id: 'agent-1', type: 'agent', name: 'worker-1', maxConcurrentClaims: 10 };
const count = await claimRepo.countByClaimant(claimant.id);
if (count < (claimant.maxConcurrentClaims ?? 5)) {
await claimService.acceptHandoff(issueId, claimant);
} Defensive patterns
Strategy: validation
Validate before calling
const max = claimant.maxConcurrentClaims ?? 5;
const current = await claimRepository.countByClaimant(claimant.id);
if (current >= max) {
// pick a different target or wait
throw new Error(`${claimant.id} at capacity (${current}/${max})`);
}
await claimService.acceptHandoff(issueId, claimant); Try / catch
try {
await claimService.acceptHandoff(issueId, claimant);
} catch (e) {
if (e instanceof ClaimOperationError && e.code === 'MAX_CLAIMS_EXCEEDED') {
// re-route to a less-loaded agent or backoff and retry
return rerouteHandoff(issueId);
}
throw e;
} Prevention
- Set maxConcurrentClaims explicitly on every Claimant rather than relying on the default 5.
- Have the load balancer consult getSwarmLoad before choosing a handoff target.
- Release or complete claims promptly so capacity is reclaimed.
When it happens
Trigger: An agent already at its concurrency limit accepts another handoff; maxConcurrentClaims is undefined so the default of 5 is enforced; a burst of handoffs routed to one agent pushes it over the limit between the load balancer's check and the accept call.
Common situations: Agent config omits maxConcurrentClaims and silently inherits 5; load balancer targeting is skewed toward one agent; long-running claims are not released promptly so the count never drops.
Related errors
- HANDOFF_PENDING
- CLAIMANT_NOT_FOUND
- HANDOFF_NOT_FOUND
- Max sessions (${this.config.maxSessions}) reached
- Invalid target format: ${target}. Use agent:<id> or human:<i
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/0468cea406e0c68a.
Report an issue: GitHub.