{"record":{"id":"4be26dafdd3ad2f0","repo":"sinelaw/fresh","slug":"cannot-reach-the-fresh-editor-for-session-its-control-socket","errorCode":null,"errorMessage":"cannot reach the Fresh editor for session '{}': its control socket ({}) could not be reached because connecting to it was denied. The editor is most likely running — the socket simply lives outside this process's sandbox. Re-run this command outside the sandbox.","messagePattern":"cannot reach the Fresh editor for session '(.+?)': its control socket \\((.+?)\\) could not be reached because connecting to it was denied\\. The editor is most likely running — the socket simply lives outside this process's sandbox\\. Re-run this command outside the sandbox\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/main.rs","lineNumber":3532,"sourceCode":"        rest.push(tokens[i]);\n        i += 1;\n    }\n    (session, rest)\n}\n\n/// Resolve the control socket for a command-channel verb.\n///\n/// The default target is the current workspace, named by `$FRESH_SESSION`;\n/// `--session <id>` overrides it. Unlike `run_open_files_command`, this never\n/// spawns a daemon — these verbs only make sense against a live editor, so a\n/// missing session or dead server is a hard error.\n/// The error for \"the socket is there, but this process may not reach it\".\n///\n/// Worded so the reader can act: an agent that can re-run outside its sandbox\n/// needs to be told that is the fix, and told it in terms it can match on. The\n/// injected \"Teach Fresh CLI\" contract points at this phrasing.\nfn socket_denied_error(session: &str, socket_paths: &SocketPaths) -> anyhow::Error {\n    anyhow::anyhow!(\n        \"cannot reach the Fresh editor for session '{}': its control socket ({}) \\\n         could not be reached because connecting to it was denied. The editor is \\\n         most likely running — the socket simply lives outside this process's \\\n         sandbox. Re-run this command outside the sandbox.\",\n        session,\n        socket_paths.control.display(),\n    )\n}\n\nfn resolve_cmd_socket(session_override: Option<&str>) -> AnyhowResult<SocketPaths> {\n    let session = match session_override {\n        Some(s) if !s.trim().is_empty() => s.to_string(),\n        _ => match std::env::var(\"FRESH_SESSION\") {\n            Ok(s) if !s.trim().is_empty() => s,\n            _ => anyhow::bail!(\n                \"not inside a Fresh session; set --session <id> (or run inside a \\\n                 Fresh workspace so $FRESH_SESSION is set)\"\n            ),","sourceCodeStart":3514,"sourceCodeEnd":3550,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/main.rs#L3514-L3550","documentation":"Produced by `socket_denied_error` when connecting to the session's control socket fails with a permission/denied error: the socket file exists and the editor is almost certainly alive, but this process's sandbox (e.g. an agent sandbox) forbids reaching it. Fresh deliberately worded the message as an actionable instruction for automated agents: re-run the command outside the sandbox.","triggerScenarios":"Calling any Fresh CLI command that targets an existing session (`FRESH_SESSION`) from inside a sandboxed process whose connect() to the control socket path is denied by the sandbox policy.","commonSituations":"Running CLI commands from within an AI coding agent's sandboxed shell; container/seccomp/landlock rules blocking unix-socket connect; running as a different user without rights to the socket file.","solutions":["Re-run the command outside the sandbox, as the message instructs.","If you control the sandbox policy, allow connect access to the control socket path (socket_paths.control).","Verify user/permissions on the socket file if not sandbox-related (ls -l, chown/chmod as needed)."],"exampleFix":"// before (agent sandboxed, fails)\n// inside sandbox: fresh-cli open foo.rs\n// after: escape the sandbox for this one command\n// $ fresh-cli open foo.rs   (run in the host shell, not the sandboxed tool)","handlingStrategy":"fallback","validationCode":"fn can_reach_socket(p: &std::path::Path) -> bool {\n    std::os::unix::net::UnixStream::connect(p).is_ok()\n}","typeGuard":null,"tryCatchPattern":"match run_cmd() {\n    Err(e) if e.to_string().contains(\"connecting to it was denied\") => {\n        eprintln!(\"hint: re-run outside the sandbox\");\n        std::process::exit(2);\n    }\n    other => other?,\n}","preventionTips":["Detect sandboxed environments (env markers) before invoking Fresh CLI against a live session","Document the outside-the-sandbox requirement in agent instructions","Grant sandbox policy exceptions for the control socket path if you own the sandbox","Check socket file permissions when not sandbox-related"],"tags":["ipc","permissions","sandbox","unix-socket"],"backgroundTag":"permission-denied","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}