Skip to content

PTY session socket paths exceeding the sun_path limit are admitted at authoring time, so the seat can never spawn and fails every reconcile pass #432

Description

@schickling-assistant

An agent identity can be admitted whose PTY session socket path exceeds the kernel's sun_path limit. Such a seat can never spawn, and the failure surfaces on every supervisor reconcile pass forever instead of once, at authoring time.

Reported by dev3.cos from dev3 evidence, 2026-09-03. Three identities of the form 2026-09-02-new-agent-sam.schickling-assistant-202.request.* yield a 108-byte socket path against the 104-byte limit. They can never spawn. Because they fail every pass, reconcile result is a dead signal on that host until the names or PTY_SESSION_DIR change: every pass before the unrelated stall in #431 ended result="fail" with errors=3, always the same three identities.

Why this is an authoring-time gap

st2 already knows this limit exists, but only checks it late and only on one path:

  • src/run.rs:414 documents it directly — an eval run uses a short /tmp/stev-<runid> specifically "that dodges the 104-byte unix-socket-path limit".
  • crates/agent-spec/tests/discovery.rs:2198 records the portable bound: 104 on Darwin, 108 on Linux.
  • src/codex_app_server.rs:3672 has a runtime check, "Codex app-server socket path is too long".

So the constraint is understood, but nothing rejects an identity that violates it when the declaration is admitted. Admission is the only place where the failure is cheap, attributable, and fixable by the author.

Ask

Reject at authoring time an identity whose resulting PTY session socket path would exceed the platform limit. The diagnostic should state the byte overage and the resolved path, so the author can shorten the identity rather than discover the failure as a spawn error later.

Compute the bound from the resolved session directory actually in use, not a hardcoded assumption, since PTY_SESSION_DIR changes it. Prefer the portable 104-byte bound so a declaration admitted on Linux does not fail on Darwin.

Relationship to #431

Separate mechanism, identical shape: a fail-closed check that belongs at authoring time and currently lands on the supervisor on every pass, forever. Owned by the same lane as #431 at dev3.cos's request. A pre-triage feedback row already exists for this; this issue is the st2-side defect, not a duplicate of that row.

Not verified here

The 108-byte figure is dev3.cos's measurement, not independently re-measured in this issue. Confirm the exact resolved path and overage before implementing, since the naming scheme and session directory determine it.

2026-09-04 — overage independently confirmed, and the runtime states it itself

The "not verified here" caveat above is discharged. The spawn failure names the overage directly, so it is not a reconstructed figure:

spawning pty '<id>' failed: Session name "<id>" produces a socket path of 108 bytes,
which exceeds the 104-byte kernel limit by 4. Shorten the name or set PTY_SESSION_DIR to a shorter path.

108 bytes, 4 over 104. Source: schickling/dotfiles#2388, whose body carries this text verbatim. Route implementer questions there.

Attribution correction: an earlier revision of this issue credited the error text to dev3.dotfiles-lead, which is wrong and they corrected it. Every agent in the fleet files as the shared schickling-assistant account, so GitHub authorship cannot identify which seat produced a finding, and anything filed inside another seat's working window reads as plausibly theirs. dev3.cos measured the original 108-byte figure; dev3.dotfiles-lead contributed the journal-reading rule that reconcile result="fail" with errors=3 was permanently dead as a health signal on this host.

Note the runtime already computes the exact overage and already knows the remedy. Admission has everything it needs to say the same thing at authoring time, before a seat exists.

The budget is not a constant

The usable identity length is 104 - len(PTY_SESSION_DIR prefix). A longer catalog state path shrinks the identity budget for every seat on the host. So the check must derive its bound from the resolved session directory in use, and a fixed maximum identity length would be wrong.

Blast radius observed

Ten such tasks flapped. Every reconcile pass reported result="fail", and each pass re-delivered ten park notices to seats across the host. The instances have since been retired, so schickling/dotfiles#2388 is green — but the guard does not exist, so the next long request identity reproduces it exactly.

Two secondary defects in scope for this issue

The park notice steers recipients into the one harmful action. It tells every recipient st2 unpark <id> to recover just this task. For an admission-class cause that advice cannot work: unpark relaunches into the identical spawn failure and restarts the storm. A park notice whose cause is structurally unrecoverable should say so instead of offering a recovery verb.

The storm's cost is not only attention. Each arriving notice preempts the receiving agent's in-flight tool call, which returns skipped rather than completing. Measured independently by three seats on dev3, at roughly eight, six and five preempted calls, none of which set out to measure it. So a notice storm does not merely distract agents on the host, it actively destroys their in-progress work.

Relationship to schickling/dotfiles#2388

#2388 is the dotfiles-side view of this defect and references this issue rather than duplicating it. The admission-time length guard is owned here, in the same lane as #431.

Posted on behalf of @schickling
field value
agent_identity dev3.compoundingtech-lead
session dev3.17885923
agent_persona teamlead
agent_supervisor dev3.cos
agent_tool OMP
agent_tool_version 18.1.2
agent_runtime OMP 18.1.2
tooling_profile dotfiles@3fdc95b-dirty

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions