{"record":{"id":"69e45543d5e515a4","repo":"hcengineering/platform","slug":"failed-to-get-endpoint-for-container-kind-er","errorCode":null,"errorMessage":"Failed to get endpoint for container ${kind}: ${err.message}","messagePattern":"Failed to get endpoint for container (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"foundations/net/packages/core/src/network.ts","lineNumber":418,"sourceCode":"    const pid = ++this.pidCounter\n    this.pending.set(pid, { agent: agent.id, kind, options, promise: record, clients: new Set(clients) })\n\n    // Wait for endpoint to be established\n    try {\n      const recordImpl = await record\n\n      agent.containers.add(recordImpl.record.uuid)\n\n      this.eventQueue.push({\n        agents: [],\n        containers: [{ container: recordImpl.record, event: NetworkEventKind.added }]\n      })\n\n      // TODO:  What if container started with same id?\n      this._containers.set(recordImpl.record.uuid, recordImpl)\n      return recordImpl\n    } catch (err: any) {\n      throw new Error(`Failed to get endpoint for container ${kind}: ${err.message}`)\n    } finally {\n      this.pending.delete(pid)\n    }\n  }\n\n  async release (client: ClientUuid, uuid: ContainerUuid): Promise<void> {\n    const _client = this._clients.get(client)\n    _client?.containers.delete(uuid)\n\n    const existing = this._containers.get(uuid)\n    if (existing !== undefined) {\n      existing.clients.delete(client)\n      if (existing.clients.size === 0) {\n        this._orphanedContainers.set(existing.record.uuid, {\n          container: existing,\n          time: this.tickManager.now()\n        })\n      }","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/net/packages/core/src/network.ts#L400-L436","documentation":"Network.getContainer asks the selected agent's api.get(kind, options) to start the container and return its [uuid, endpoint]. Any error from that remote call (agent unreachable, container image/creation failure, timeout) is wrapped in this error with the original message appended. The finally block removes the pending marker, so the failure is per-attempt.","triggerScenarios":"The chosen agent's api.get throws — network partition to the agent, agent crashed mid-call, container runtime failure to start the image, endpoint allocation failure, or timeout while awaiting the endpoint.","commonSituations":"Agent host down or DNS/ports blocked; container registry auth failure or missing image; resource exhaustion on the agent node (OOM, no free ports); transient timeout under load that a retry would clear.","solutions":["Read the inner err.message in the thrown text to identify the root cause (unreachable agent vs container start failure).","Verify the selected agent is reachable and healthy (ping its api endpoint, check its process).","Fix the container-side cause: image exists and pullable, runtime configured, resources/ports available.","Retry getContainer — the round-robin index advances so the next attempt may pick a different, healthy agent.","Add a fallback: try again with different options (smaller resources) or on another network/agent pool."],"exampleFix":"// before\nconst rec = await network.getContainer(clientId, kind) // throws 'Failed to get endpoint...'\n// after\nlet rec\ntry {\n  rec = await network.getContainer(clientId, kind)\n} catch (e) {\n  console.error('container start failed:', e.message)\n  rec = await network.getContainer(clientId, kind) // retry, may pick another agent\n}","handlingStrategy":"retry","validationCode":"// Pre-check agent health before scheduling:\nfor (const a of network.agents?.values?.() ?? []) {\n  if (!a.kinds.includes(kind)) continue\n  const healthy = await pingAgent(a) // e.g. api.ping with timeout\n  if (healthy) { /* proceed */ }\n}","typeGuard":"function isEndpointAllocated(r: { record?: { uuid?: string; endpoint?: string } }): boolean {\n  return typeof r.record?.uuid === 'string' && typeof r.record.endpoint === 'string'\n}","tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try {\n    return await network.getContainer(clientId, kind, options)\n  } catch (e) {\n    if (!(e as Error).message.startsWith('Failed to get endpoint')) throw e\n    console.warn(`container start attempt ${attempt + 1} failed: ${e.message}`)\n    await sleep(2 ** attempt * 500) // backoff; round-robin may pick another agent\n  }\n}\nthrow new Error(`could not start container ${kind} after retries`)","preventionTips":["Keep agent nodes healthy: monitor CPU/memory/ports and registry auth before scaling requests.","Always log the wrapped inner err.message to distinguish agent-unreachable from container-start failures.","Use retries with backoff since round-robin advances to a different agent each attempt.","Set explicit timeouts on agent api calls so failures fail fast and are retriable."],"tags":["container-start","agent-communication","endpoint","wrapping"],"backgroundTag":"container-endpoint-failed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}