{"record":{"id":"34d51a9e3ca643ab","repo":"facebook/flow","slug":"daemon-child-failed-to-connect-to-parent-out-sock","errorCode":null,"errorMessage":"Daemon child: failed to connect to parent out-socket (child read end): {}","messagePattern":"Daemon child: failed to connect to parent out-socket \\(child read end\\): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"rust_port/crates/flow_daemon/src/daemon.rs","lineNumber":536,"sourceCode":"        ),\n        child,\n    })\n}\n\npub fn check_entry_point() {\n    let Some((entry_name, context)) = entry::get_context() else {\n        return;\n    };\n    entry::clear_context();\n    let entry::Context {\n        parent_in_addr,\n        parent_out_addr,\n        token,\n        param_bytes,\n    } = context;\n\n    let mut child_in_sock = TcpStream::connect(parent_out_addr).unwrap_or_else(|e| {\n        panic!(\n            \"Daemon child: failed to connect to parent out-socket (child read end): {}\",\n            e\n        )\n    });\n    child_in_sock.set_nodelay(true).unwrap_or_else(|e| {\n        panic!(\n            \"Daemon child: failed to set TCP_NODELAY on parent out-socket: {}\",\n            e\n        )\n    });\n    child_in_sock.write_all(&token).unwrap_or_else(|e| {\n        panic!(\n            \"Daemon child: failed to write token to parent out-socket: {}\",\n            e\n        )\n    });\n    let mut child_out_sock = TcpStream::connect(parent_in_addr).unwrap_or_else(|e| {\n        panic!(","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_daemon/src/daemon.rs#L518-L554","documentation":"After fork/spawn, the daemon child reconnects to the parent's sockets used as its stdin/stdout channels. This panic fires when TcpStream::connect to parent_out_addr (the child's read end) fails: the parent already exited or closed its listener, the loopback connect was refused/reset, the backlog was exhausted, or loopback networking is unavailable in the environment.","triggerScenarios":"Parent flow process dies between spawning the child and the child's connect; sandbox/container denies loopback TCP connects; ephemeral port or connection-rate exhaustion; firewall/endpoint security interfering with 127.0.0.1 sockets.","commonSituations":"Flow server parent crashing on startup under memory pressure; gVisor/Firecracker-style sandboxes restricting loopback; aggressive conntrack limits; tooling that kills process trees while a daemon is spawning.","solutions":["Retry the flow command; a clean respawn usually completes the handshake","Run flow stop to clear half-spawned daemons first","In containers, confirm loopback TCP is permitted and conntrack/limits are sane","Check parent-side logs for an early crash that closed the listener"],"exampleFix":"# before\nflow check   # daemon child panics: failed to connect to parent out-socket\n\n# after\nflow stop\nflow check   # if it recurs, inspect parent crash logs / sandbox network policy","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Retry after flow stop; half-spawned daemons amplify handshake races","Verify loopback TCP is permitted in your container/sandbox profile","Keep the parent process healthy (memory, supervisors) through daemon spawn"],"tags":["daemon","socket","connect","loopback","spawn"],"backgroundTag":"connection-refused","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}