langchain-ai/deepagents · error · FileExistsError
Refusing to remove non-socket external event path: {path}
Error message
Refusing to remove non-socket external event path: {path} What it means
`_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.
Source
Thrown at libs/code/deepagents_code/event_bus.py:355
base = Path(root) if root else Path(tempfile.gettempdir())
return base / "deepagents" / f"events-{os.getpid()}.sock"
def _unlink_existing_socket(path: Path) -> None:
"""Remove a stale Unix socket without touching other filesystem entries.
Args:
path: Candidate socket path to remove.
Raises:
FileNotFoundError: If `path` does not exist.
FileExistsError: If `path` exists but is not a Unix socket.
OSError: If the entry exists but cannot be removed.
""" # noqa: DOC502 # FileNotFoundError/OSError propagate from stat/unlink
info = path.stat(follow_symlinks=False)
if not stat.S_ISSOCK(info.st_mode):
msg = f"Refusing to remove non-socket external event path: {path}"
raise FileExistsError(msg)
path.unlink()
def decode_external_event(data: bytes, *, source: str) -> ExternalEvent:
"""Decode one newline-delimited JSON external event.
Args:
data: Raw JSON line.
source: Transport-specific source label attached to the event.
Returns:
Parsed external event.
Raises:
TypeError: If the envelope is not a JSON object.
ValueError: If any envelope field is missing, of the wrong type, or
otherwise invalid.
"""View on GitHub (pinned to a1af029e6e)
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.
Example fix
# before # socket path occupied by a stale regular file rm /tmp/deepagents/events-1234.sock # actually a regular file # after # path removed; bus can bind the socket
Defensive patterns
Strategy: validation
Validate before calling
import stat
from pathlib import Path
def socket_path_is_clear(path: Path) -> bool:
try:
mode = path.stat(follow_symlinks=False).st_mode
except FileNotFoundError:
return True
return stat.S_ISSOCK(mode)
# remove or relocate non-socket entries before start()
if not socket_path_is_clear(path):
path.unlink(missing_ok=True) if path.is_file() or path.is_symlink() else None
Type guard
def is_unix_socket(path: Path) -> bool:
try:
return stat.S_ISSOCK(path.stat(follow_symlinks=False).st_mode)
except FileNotFoundError:
return False
Try / catch
try:
bus.start()
except FileExistsError as exc:
logger.error("socket path occupied by non-socket entry: %s", exc)
# pick a different path or remove the entry manually
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- UnixSocketEventSource is already started
- UnixSocketEventSource.serve_forever called before start()
- debug log directory is not a real directory: {path}
- debug log directory is not owned by the current user: {path}
- Cannot determine whether {str(left)!r} is {str(right)!r}: {e
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/03e36b6961017984.
Report an issue: GitHub.