{"record":{"id":"acfd481bb4f694c1","repo":"different-ai/openwork","slug":"agent-diagnostics-busy","errorCode":"agent_diagnostics_busy","errorMessage":"Agent diagnostics are temporarily busy","messagePattern":"Agent diagnostics are temporarily busy","errorType":"http","errorClass":"ApiError","httpStatus":429,"severity":"warning","filePath":"apps/server/src/server.ts","lineNumber":217,"sourceCode":"  agentDiagnosticsLastRun.set(key, now);\n}\n\nfunction reserveAgentDiagnosticsRun(\n  config: ServerConfig,\n  actor: Actor | undefined,\n  workspaceId: string,\n): () => void {\n  const key = agentDiagnosticsActorWorkspaceKey(actor, workspaceId);\n  const inFlight = agentDiagnosticsInFlightByServer.get(config) ?? new Set<string>();\n  agentDiagnosticsInFlightByServer.set(config, inFlight);\n  // Preserve the existing cooldown response for ordinary repeated attempts.\n  // A zero/expired cooldown still cannot bypass the in-flight reservation.\n  requireAgentDiagnosticsRateLimit(config, actor, workspaceId);\n  if (inFlight.has(key)) {\n    throw new ApiError(429, \"agent_diagnostics_in_progress\", \"Agent diagnostics are already in progress\");\n  }\n  if (inFlight.size >= AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER) {\n    throw new ApiError(429, \"agent_diagnostics_busy\", \"Agent diagnostics are temporarily busy\");\n  }\n\n  // The cooldown charge and reservation are synchronous, so no second request\n  // for this actor/workspace can slip in between them.\n  inFlight.add(key);\n  let released = false;\n  return () => {\n    if (released) return;\n    released = true;\n    inFlight.delete(key);\n  };\n}\n\nconst OPENWORK_VOICE_REALTIME_TOOLS = [\n  {\n    type: \"function\",\n    name: \"openwork_snapshot\",\n    description: \"Read the current OpenWork UI control snapshot: route, status, narration, and visible action metadata.\",","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/server/src/server.ts#L199-L235","documentation":"This 429 error is thrown by reserveAgentDiagnosticsRun when the number of concurrent agent diagnostics runs on a single server config has reached AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER. Unlike error 330 (same key already reserved), this fires for any new key once the pool is full. It is a temporary capacity backpressure signal.","triggerScenarios":"POSTing a new agent diagnostics request (unique actor/workspace key) when inFlight.size >= AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER for that server config. Multiple distinct workspaces or actors starting diagnostics simultaneously.","commonSituations":"CI pipelines running diagnostics for many workspaces in parallel against one server; org-wide 'diagnose everything' scripts; bursts after a mass config change.","solutions":["Reduce concurrency of diagnostics calls client-side (semaphore/queue)","Retry after a delay using exponential backoff until a slot frees","Stagger diagnostics runs across workspaces","Raise AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER only if server capacity allows"],"exampleFix":"// before\nawait Promise.all(workspaces.map(w => runDiagnostics(w.id)));\n// after\nfor (const w of workspaces) {\n  await withConcurrencyLimit(2, () => runDiagnostics(w.id));\n}","handlingStrategy":"retry","validationCode":"// cap client concurrency below the server limit\nconst MAX_CONCURRENT = 2; // < AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER\nif (outstandingDiagnostics >= MAX_CONCURRENT) await queue.wait();","typeGuard":null,"tryCatchPattern":"try {\n  await reserveAgentDiagnosticsRun(config);\n} catch (e) {\n  if (e.code === \"agent_diagnostics_busy\") {\n    await sleep(backoffMs);\n    return reserveWithRetry(config); // exponential backoff\n  }\n  throw e;\n}","preventionTips":["Serialize diagnostics runs with a client-side semaphore","Stagger scheduled diagnostics across workspaces","Back off exponentially on 429 responses"],"tags":["rate-limit","capacity","concurrency"],"backgroundTag":"resource-already-in-progress","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}