e2b-dev / e2b-dev/runtime

api: client-disconnect body-read failures are misclassified as auth errors (400 WARN noise)

Open
#3,413 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
1.6k
Forks
438
PR merge metrics
No merged PRs in 30d

Description

Problem

Under high concurrency (e.g. 1 000 simultaneous sandbox creates after a period of idleness), the orchestration-api emits a flood of WARN log lines and 400 responses that look like authentication failures:

WARN  error in openapi3filter.SecurityRequirementsError: security requirements failed: reading failed: read tcp 192.168.0.146:3000->100.64.x.x:port: i/o timeout
WARN  error in openapi3filter.SecurityRequirementsError: security requirements failed: reading failed: read tcp 192.168.0.146:3000->100.64.x.x:port: connection reset by peer

These are not auth failures. They are network-level events where either:

  • the server's ReadTimeout: 10s expired while the goroutine was queued waiting to be scheduled (under heavy load), or
  • the client SDK's own timeout fired and closed the connection before the server read the body.

Root cause

kin-openapi@v0.139.0 (openapi3filter/validate_request.go:448) reads the entire request body via io.ReadAll before calling any AuthenticationFunc. When that TCP read fails it returns:

&RequestError{Reason: "reading failed", Err: <net.Error>}

validateSecurityRequirements then wraps this in SecurityRequirementsError. processCustomErrors in packages/api/internal/utils/error.go has no special handling for this case, so it falls through to the generic securityErrPrefix path. ErrorHandler then calls telemetry.ReportError (sets OTel span error status → WARN log line), adds to c.Errors, and returns HTTP 400 — all of which suggest an auth failure to every downstream observer: dashboards, alerts, on-call.

Impact

  • Auth-failure dashboards and alerts fire on client-side network noise.
  • Incident responders waste time investigating fake 401/400 spikes.
  • Real auth failures are diluted by the noise, increasing MTTD.

Fix

In processCustomErrors, detect RequestError{Reason:"reading failed"} with an underlying net.Error and return it under a dedicated clientDisconnectPrefix. ErrorHandler handles this prefix early: records an OTel span event (informational, not error status) via telemetry.ReportEvent, and responds 499 without adding to c.Errors.

Result:

  • No more fake SecurityRequirementsError WARN logs for client disconnects.
  • 499 responses are queryable in metrics separately from 400/401/403.
  • Auth-failure alerts stay clean.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/api/internal/utils/error.go, tracing processCustomErrors and ErrorHandler, then review the request-body failure described at kin-openapi/openapi3filter/validate_request.go:448. Verify how telemetry.ReportError, telemetry.ReportEvent, c.Errors, and response status are currently used. Done means client-disconnect body-read failures are separated from authentication errors and produce the described 499 behavior without error-status logging.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend-api-design, networking, observability
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.