langchain-ai/deepagents · error · DeepAgentsHomeError
Cannot determine whether {str(left)!r} is {str(right)!r}: {e
Error message
Cannot determine whether {str(left)!r} is {str(right)!r}: {exc.strerror or exc}. Fix the permissions on those paths, or set DEEPAGENTS_HOME to a path that can be read. What it means
_same_directory compares two paths for identity (to reject degenerate profile roots like DEEPAGENTS_HOME=/ or /tmp). If the underlying OS calls raise OSError (e.g. EACCES while stat'ing the paths), it re-raises as DeepAgentsHomeError because the library cannot prove the paths differ. This is a fail-closed guard on the trust boundary.
Source
Thrown at libs/code/deepagents_code/_paths.py:662
try:
return Path(left).samefile(right)
except FileNotFoundError:
# A profile root that is not there yet cannot be the home directory,
# and the lexical comparison above has already ruled out the
# spelling-only case.
logger.debug("Could not compare %s with %s: one is missing", left, right)
return False
except OSError as exc:
# EACCES, ELOOP, EIO, ESTALE: the answer is unknown, not "different".
# The whole point of `samefile` here is to catch the non-lexical
# spellings the comparison above misses, so returning `False` would
# accept exactly the aliases this guard exists to reject.
msg = (
f"Cannot determine whether {str(left)!r} is {str(right)!r}: "
f"{exc.strerror or exc}. Fix the permissions on those paths, or "
"set DEEPAGENTS_HOME to a path that can be read."
)
raise DeepAgentsHomeError(msg) from exc
def _reject_degenerate_root(root: Path, launch_home: Path | None) -> None:
"""Reject a resolved profile root that would scatter state.
A profile root is a trust boundary that owns everything beneath it, so it
must be a directory of its own. The rejected cases all resolve to something
the user did not mean:
- The filesystem root, from `DEEPAGENTS_HOME=/` or a `..` chain that walks
past it, would put credentials in `/.state/auth.json`.
- The home directory itself, from a `DEEPAGENTS_HOME=~/` typo, would make
the profile dotenv the user's generic `~/.env` and load it as trusted
configuration.
- An existing non-directory cannot hold a profile at all.
- A root that exists but cannot be read. Every later access fails one file
at a time, and each failure looks like a first run, so reject it once
here with the real cause.View on GitHub (pinned to a1af029e6e)
Solutions
- Fix permissions on the path and its parents (chmod/chown so the current user can read+search them).
- Point DEEPAGENTS_HOME at a readable, user-owned absolute path.
- Avoid placing the profile root under system-restricted directories like / or /root.
Example fix
// before: DEEPAGENTS_HOME=/root/.deepagents as non-root user // after export DEEPAGENTS_HOME="$HOME/.deepagents"
Defensive patterns
Strategy: try-catch
Validate before calling
import os
from pathlib import Path
root = Path(os.environ.get('DEEPAGENTS_HOME', ''))
if root.exists():
for p in (root, *root.parents[:2]):
if not os.access(p, os.R_OK | os.X_OK):
raise SystemExit(f'unreadable path in DEEPAGENTS_HOME chain: {p}') Try / catch
try:
root = _resolve_profile_root()
except DeepAgentsHomeError as exc:
if 'Cannot determine whether' in str(exc):
raise SystemExit(f'Fix permissions for DEEPAGENTS_HOME: {exc}') from exc
raise Prevention
- Keep DEEPAGENTS_HOME under the user's own home directory.
- Avoid pointing the profile root at /, /tmp, /root, or admin-only trees.
- Verify readability of the full path chain after restores or volume mounts.
When it happens
Trigger: DEEPAGENTS_HOME points at a path whose permission bits prevent stat/read of it or the comparison target (e.g. root or a parent is unreadable), during _reject_degenerate_root checks.
Common situations: DEEPAGENTS_HOME under a root-owned directory with mode 700 while running as a normal user; restricted mount points in containers; NFS/ACL setups where stat is denied.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- debug log directory is not owned by the current user: {path}
- Invalid DEEPAGENTS_HOME {str(root)!r}: exists but cannot be
- temporary artifact is not owned by this user
- temporary artifact permissions are too broad
- debug log directory is not a real directory: {path}
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/74e113adb37c633b.
Report an issue: GitHub.