When something is refused
Every egress refusal you can meet — before a run starts or on a single connection — with its cause and its remedy.
There are two kinds of refusal. A run refusal happens before anything is spawned: nothing ran and nothing was spent, so the remedy is cheap. A connection refusal happens inside a running agent: one connection was closed, and the agent carries on or fails depending on how it handles a broken network.
Run refusals
Each message names what was measured, what was refused and the next step.
| refusal | cause | remedy |
|---|---|---|
EGRESS-CLOSED-DEFAULT-REFUSED / egress-unavailable | the target machine cannot carry any wall: never probed, a rung this release cannot raise, netns-redirect not yes, a remote container, or vendor confinement | do the fix the message names — usually probe the machine or place the run on a machine that carries the wall. Only then consider --egress-open |
egress-unavailable with the rung <none recorded> | the same fact, reported at spawn time: the machine was never probed | probe it |
far-darwin-door-unavailable | a remote Mac's saphan is too old to stand the door, is not on its PATH, the door did not start, or could not be shown stopped at the end | install the current saphan on the Mac. If the message says no reading was taken, report it: it is not a host fault |
legacy-far-wall-unavailable | a remote Linux machine runs a different build of saphan-agent or saphan, or has none — or the dispatching machine cannot read its own build | install the current build on both machines, as the message names |
harness-far-door-lacks-policy-file | under the agent harness, the remote saphan is too old to take a policy file | install the current build on that machine |
legacy-local-wall-unavailable | the local machine has no saphan-agent binary | install saphan-agent |
confinement-unavailable — socket path over 103 bytes | the door's socket path is too long for a Unix socket; on a remote machine the home directory's length decides it | use a shorter home path for that machine's working directory |
harness-unavailable | under run.harness = saphan-agent, the agent harness cannot compose this run — a backend that takes its prompt on standard input, a container whose host offers only the relay rung, a remote Mac with a backend that ignores the proxy wire, or an unresolvable binary directory | do what the message names — usually measure the host so the bridge rung can be chosen, or saphan config set run.harness legacy (installation-wide). A container under the legacy harness is refused as EGRESS-CLOSED-DEFAULT-REFUSED instead |
container-egress-class-network-denied | the run carries a policy, but its permission class grants the container no network | use a class that grants network: allowed, or drop the policy |
egress-baseline-unknown | the backend has no shipped baseline | dispatch with your own document (--egress-policy) or with --egress-open |
egress-open-unnamed | --egress-open was given a blank reason, no actor, or was combined with --egress-policy | give a reason and an actor, and use one flag or the other |
dispatch-loopback-lane-needs-egress-open | saphan dispatch was asked for a run whose model endpoint is on a loopback address, which no policy can name | dispatch it with saphan run … --egress-open "<reason>"; saphan dispatch has no opening flag |
egress-open-unrecorded | a run specification reached the agent with neither a policy nor a recorded opening | dispatch through saphan run / saphan dispatch, which records it |
egress-policy-claim-door-mismatch | the policy file changed between the moment it was read and the moment the door loaded it | leave the file unchanged and dispatch again |
egress-policy-unclaimed | the policy file sits where the agent itself could write it | keep the policy outside the run's working directory, capture directory and seat home |
egress-door-reported-no-digest | the door did not report which policy it loaded | a product defect: report it; do not retry |
sealed-jail-socket-reachable | in sealed mode, a host socket was still reachable from inside the run | report it with the socket path from the message |
guardrail-unavailable | the run would be recorded by the guardrail, but the guardrail cannot run inside this lane's wall | see Guardrails; the per-run way out is --egress-open |
harness-unknown | run.harness holds a value other than legacy or saphan-agent | set one of the two |
Connection refusals
A connection refusal carries one of these classes. The policy and the floor are described on Policies and What no policy can open.
| class | meaning |
|---|---|
egress-destination-not-allowed | no rule names this host |
egress-port-not-allowed | the host is named, the port is not |
egress-address-denied | the host resolved to an address on the floor |
egress-literal-not-recorded | a bare IP address that the policy does not list |
egress-resolve-failed | the name did not resolve |
egress-sni-mismatch | the TLS host name differs from the approved one, or is missing |
egress-host-unparseable | the destination is not a valid host |
egress-protocol-error, egress-method-unsupported, egress-auth-unsupported | the client spoke the proxy protocol in a way the door does not accept |
egress-upstream-unreachable | the destination was allowed but could not be reached |
egress-limit-… | a connection ceiling was exceeded |
egress-resolve-denied | on the network wall, a name the policy does not list was answered as not existing. This release writes it to no record |
egress-record-unavailable | the connection was allowed, but the decision could not be written to the record, so it was refused |
A toolchain cannot fetch
The most common case: an agent's go, npm or Gradle fetch fails — on the network wall (Linux,
containers) with a name that does not resolve or a reset connection, on macOS with 403 Forbidden.
- Check the run's policy source, the
egress_policy_sourcefield of its run record. No command or console page displays it in this release; read it from the installation's database. If it does not include the workload you expected — for exampleworkload:egress-workload-go-v1— the run did not get that registry. - Run under a shipped class or grant that the workload names — for Go,
executor-goorexecutor-container— or add the registry host to your own document and dispatch with--egress-policy. - For a one-off,
--egress-open "<reason>", which is recorded.