toeverything/AFFiNE · error · TooManyRequest

too_many_request

too_many_request

Error message

Too many requests.

What it means

Surfaced as TooManyRequest (HTTP 429) by InviteQuotaAssertService, but at this exact line it is NOT a real quota decision: it is the fail-closed branch of the catch around the native invite-quota runtime (assertWorkspaceInviteQuotaV1). When the native runtime throws and config.auth.inviteQuotaFailOpenOnRuntimeError is false, the service rejects the invite rather than risk allowing abuse.

Source

Thrown at packages/backend/server/src/core/workspaces/abuse.ts:276

          ? 'fail_open'
          : 'fail_closed',
      });
      this.logger.error('Workspace invite quota native assert failed', {
        userId: input.actorUserId,
        workspaceId: input.workspaceId,
        targetCount: input.targetCount,
        targetDomainsSummary: input.targetDomains,
        sourceTrusted: input.source?.trusted ?? false,
        country: input.source?.country,
        asn: input.source?.asn,
        requestId: input.requestId,
        cfRay: input.source?.rayId,
        error: message,
      });
      if (this.config.auth.inviteQuotaFailOpenOnRuntimeError) {
        return { decision: { allowed: true, requested: input.targetCount } };
      }
      throw new TooManyRequest();
    }
    metrics.workspace
      .counter('invite_quota_requested_targets')
      .add(input.targetCount);
    metrics.workspace
      .histogram('invite_quota_counter_latency_ms')
      .record(Date.now() - start);

    if (!decision.allowed) {
      metrics.workspace.counter('invite_quota_rejected').add(1, {
        reason: decision.reason ?? 'unknown',
      });
      metrics.workspace.counter('invite_quota_reject_by_reason').add(1, {
        reason: decision.reason ?? 'unknown',
      });
      if (this.config.auth.inviteQuotaShadowMode) {
        this.logger.warn('Workspace invite quota shadow rejected', {
          userId: input.actorUserId,

View on GitHub (pinned to 26c515e050)

Solutions

  1. Inspect server logs for 'Workspace invite quota native assert failed' and fix the failing runtime dependency.
  2. If you intentionally want invites to proceed during runtime outages, set auth.inviteQuotaFailOpenOnRuntimeError=true (weigh abuse risk).
  3. Retry the invite after the runtime service recovers; surface retry-after guidance to the user.
  4. Verify the runtime provider is reachable and healthy (network, auth, capacity).

Example fix

// before (config)
auth: { inviteQuotaFailOpenOnRuntimeError: false }
// after (opt-in fail-open during runtime outages)
auth: { inviteQuotaFailOpenOnRuntimeError: true }
Defensive patterns

Strategy: retry

Validate before calling

// no client input prevents this; preflight the abuse runtime
const healthy = await adminRuntimeHealthCheck()
if (!healthy) deferInviteBatch()

Try / catch

try {
  await workspace.inviteMembers(emails)
} catch (e) {
  if (e.code === 'too_many_request') { await sleep(backoffMs); await workspace.inviteMembers(emails) }
  else throw e
}

Prevention

When it happens

Trigger: The invite-quota native runtime crashes, times out, or returns a non-Error failure while processing a workspace invite, AND the server is configured fail-closed (auth.inviteQuotaFailOpenOnRuntimeError=false). The user sees 429 even though the quota itself was never evaluated.

Common situations: The abuse-detection runtime is down or being deployed; a bad deploy of the native module; a network blip between backend and quota runtime; flipping fail-open off during a shared infra outage.

Understand the failure class

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/019a1deb3a8c9bcf. Report an issue: GitHub.