{"record":{"id":"03e36b6961017984","repo":"langchain-ai/deepagents","slug":"refusing-to-remove-non-socket-external-event-path","errorCode":null,"errorMessage":"Refusing to remove non-socket external event path: {path}","messagePattern":"Refusing to remove non-socket external event path: (.+?)","errorType":"exception","errorClass":"FileExistsError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/event_bus.py","lineNumber":355,"sourceCode":"    base = Path(root) if root else Path(tempfile.gettempdir())\n    return base / \"deepagents\" / f\"events-{os.getpid()}.sock\"\n\n\ndef _unlink_existing_socket(path: Path) -> None:\n    \"\"\"Remove a stale Unix socket without touching other filesystem entries.\n\n    Args:\n        path: Candidate socket path to remove.\n\n    Raises:\n        FileNotFoundError: If `path` does not exist.\n        FileExistsError: If `path` exists but is not a Unix socket.\n        OSError: If the entry exists but cannot be removed.\n    \"\"\"  # noqa: DOC502  # FileNotFoundError/OSError propagate from stat/unlink\n    info = path.stat(follow_symlinks=False)\n    if not stat.S_ISSOCK(info.st_mode):\n        msg = f\"Refusing to remove non-socket external event path: {path}\"\n        raise FileExistsError(msg)\n    path.unlink()\n\n\ndef decode_external_event(data: bytes, *, source: str) -> ExternalEvent:\n    \"\"\"Decode one newline-delimited JSON external event.\n\n    Args:\n        data: Raw JSON line.\n        source: Transport-specific source label attached to the event.\n\n    Returns:\n        Parsed external event.\n\n    Raises:\n        TypeError: If the envelope is not a JSON object.\n        ValueError: If any envelope field is missing, of the wrong type, or\n            otherwise invalid.\n    \"\"\"","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/event_bus.py#L337-L373","documentation":"`_unlink_existing_socket` cleans up a stale Unix socket path before the external event bus binds it. To protect against deleting unrelated files, it stats the path with symlinks not followed and refuses to unlink anything that is not a socket. It raises `FileExistsError` so the caller can report that the configured path collides with a non-socket filesystem entry rather than silently removing it.","triggerScenarios":"Calling `start()` or `stop()` (or `_cleanup_external_event_source_sync`) when the socket path (default `$(XDG_RUNTIME_DIR or /tmp)/deepagents/events-<pid>.sock`, or a custom path) exists but is a regular file, directory, FIFO, or symlink to a non-socket, e.g. leftover from a config change or created by another process.","commonSituations":"A user pre-created the `deepagents/` directory with a placeholder file at the socket path; a previous crash left a regular file where a socket used to be; the custom socket path points at a log or PID file; a symlinked path resolves to a plain file.","solutions":["Inspect the path in the message and delete or rename the non-socket entry manually, then retry `start()`.","If a custom socket path is configured, change it to an unused location instead of reusing an existing file path.","If the entry is a symlink, replace the symlink target with an actual Unix socket or remove the symlink.","Check nothing else (another process) owns that path; pick a per-process path or different XDG_RUNTIME_DIR."],"exampleFix":"# before\n# socket path occupied by a stale regular file\nrm /tmp/deepagents/events-1234.sock   # actually a regular file\n\n# after\n# path removed; bus can bind the socket\n","handlingStrategy":"validation","validationCode":"import stat\nfrom pathlib import Path\n\ndef socket_path_is_clear(path: Path) -> bool:\n    try:\n        mode = path.stat(follow_symlinks=False).st_mode\n    except FileNotFoundError:\n        return True\n    return stat.S_ISSOCK(mode)\n\n# remove or relocate non-socket entries before start()\nif not socket_path_is_clear(path):\n    path.unlink(missing_ok=True) if path.is_file() or path.is_symlink() else None\n","typeGuard":"def is_unix_socket(path: Path) -> bool:\n    try:\n        return stat.S_ISSOCK(path.stat(follow_symlinks=False).st_mode)\n    except FileNotFoundError:\n        return False\n","tryCatchPattern":"try:\n    bus.start()\nexcept FileExistsError as exc:\n    logger.error(\"socket path occupied by non-socket entry: %s\", exc)\n    # pick a different path or remove the entry manually\n","preventionTips":["Never place regular files, logs, or PID files under the configured socket directory.","Prefer the default per-process socket path instead of custom shared paths.","Clean up crash leftovers with `stat`-based checks, not blind `rm`.","Avoid symlinks in socket paths."],"tags":["filesystem","unix-socket","event-bus"],"backgroundTag":"socket-path-collision","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}