Skip to content

startMount: two unwrapped execs make a transport rejection unclassifiable (100% JIT provision failure in prod) #45

Description

@khaliqgant

Impact

Every forceProvision JIT sandbox provision through agentrelay.com is currently failing at the Relayfile mount. Measured 5/5 against production today:

5/5  HTTP 503  mountElapsedMs 112143 / 131990 / 122960 / 133527 / 117733
     phase: relayfile_mount_invocation_unknown

With the mount disabled (mountRelayfile:false), the same route is 5/5 HTTP 201 in 21–28s. The mount is the sole blocker. This has been blocking factory-cloud dispatch end-to-end for ~24h.

What the timings show

Production cloud-web-worker logs, one representative request:

phase elapsed
sandbox_provision (Daytona create) 1.34s
cli_credential_setup 9.19s
enrollment_token_mint 1.40s
relayfile_token_mint 0.76s
relayfile_credentials_seed 0.19s
startMount 122.0s → throw

Daytona itself is fast. The credentials seed completes at mountElapsedMs 951, so the ~121s hang begins essentially immediately inside startMount.

The defect

orchestrator.js#startMount in 0.1.12 wraps some of its execs so a rejection becomes a classified error, but not all:

exec wrapped? on rejection
mkdir mount path yes (Failed to create relayfile mount path:) classified
initial-sync launch no unclassified
status probe (poll loop) yes (Failed to check relayfile initial sync status:) classified
daemon start no unclassified

Every throw that embeds sandbox command output is one the caller's classifier recognises. So an unclassified error can only have come from one of those two unwrapped runScript calls rejecting — and ~122s matches the ~120s Daytona proxy read timeout your own comment in this file cites:

// The initial sync can outlive any single exec (Daytona's proxy read
// timeout is ~120s and callers wrap execs in client-side fail-fasts), so
// it runs detached in the sandbox ...

The detached launch shell itself looks correct (nohup sh -c '<runner>' >/dev/null 2>&1 & echo $! — fds redirected, setsid where available), which is why this needs the cause to be readable before guessing further.

Asks

  1. Wrap the two remaining execs the way mkdir and the status probe already are, so a transport rejection lands on a named phase (relayfile_mount_*_not_invoked / _invoked_exited) instead of falling through to the caller's unknown bucket. This is the cheap part and it is what makes the next failure self-describing.
  2. Then determine which of the two is hanging and why. Given the launch shell detaches correctly, the daemon start (buildRelayfileMountStartShell) is worth looking at first — a foreground daemon that never closes its exec channel would hang exactly this way.

Consumer-side context: cloud discards the cause on this path today, which is why it read as opaque. AgentWorkforce/cloud#3244 fixes cloud's half so the cause is logged; this issue is the actual fault.

Deliberately filed without the factory readiness label — this needs a human to pick the approach, not an auto-dispatch.

Reported by cloud-ensure-fix-r1.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions