langchain-ai/deepagents · error · OSError

temporary artifact is not owned by this user

Error message

temporary artifact is not owned by this user

What it means

Raised by `_allocate_temp_artifact` when the freshly created temp artifact's `st_uid` does not match the current process's `os.getuid()`. The library throws this to prevent trusting (and later deleting) a file that was swapped in by another local user — a classic TOCTOU hardening check on the shared temp directory.

Source

Thrown at libs/code/deepagents_code/auto_mode.py:1059

) -> AutoTempArtifact:
    data = content.encode("utf-8")
    temp_root = Path(tempfile.gettempdir()).absolute()
    file_descriptor, raw_path = tempfile.mkstemp(
        prefix=_TEMP_ARTIFACT_PREFIX,
        suffix=suffix,
        dir=temp_root,
    )
    file_path = Path(raw_path)
    complete = False
    try:
        file_stat = _write_temp_artifact_bytes(file_descriptor, data)
        if not stat.S_ISREG(file_stat.st_mode):
            msg = "temporary artifact is not a regular file"
            raise OSError(msg)
        getuid = getattr(os, "getuid", None)
        if callable(getuid) and file_stat.st_uid != getuid():
            msg = "temporary artifact is not owned by this user"
            raise OSError(msg)
        if os.name != "nt" and stat.S_IMODE(file_stat.st_mode) & 0o077:
            msg = "temporary artifact permissions are too broad"
            raise OSError(msg)
        artifact = AutoTempArtifact(
            allocation_id=uuid4().hex,
            file_path=str(file_path),
            thread_key=thread_key,
            turn_id=turn_id,
            created_by_tool_call_id=tool_call_id,
            file_device=file_stat.st_dev,
            file_inode=file_stat.st_ino,
        )
        complete = True
        return artifact
    finally:
        with contextlib.suppress(OSError):
            os.close(file_descriptor)
        if not complete:

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Ensure the process does not change uid between creating and stat-ing the file (avoid setuid helpers mid-run)
  2. Point `TMPDIR` at a directory owned by and writable only by the current user (e.g. a private run dir) so no other uid can race it
  3. Check the temp directory has the sticky bit (`ls -ld /tmp` shows `drwxrwxrwt`) and correct ownership
  4. If it appears in tests, verify any `os.getuid` monkeypatching matches the artifact's `st_uid`
Defensive patterns

Strategy: validation

Validate before calling

import os, tempfile, stat
tmp = tempfile.gettempdir()
st = os.stat(tmp)
if os.name == "posix":
    assert st.st_uid == os.getuid() or (st.st_mode & stat.S_ISVTX), "temp dir not sticky-bit protected"
    assert not (st.st_mode & 0o002 and not (st.st_mode & stat.S_ISVTX)), "world-writable temp dir without sticky bit"

Try / catch

try:
    artifact = create_temp_artifact(content=content, suffix=".txt")
except OSError as exc:
    if "not owned by this user" in str(exc):
        switch_to_private_tmpdir_and_retry()
    else:
        raise

Prevention

When it happens

Trigger: Calling `create_temp_artifact` where the `mkstemp` result is owned by a different uid — only possible on multi-user POSIX systems if the temp directory permits it (e.g. a sticky-bit directory with hostile content, uid changes via setuid, or a symlink attack replacing the file).

Common situations: Running the agent under sudo/setuid where uid flips mid-run; a shared/writable `/tmp` where another user races the mkstemp; `TMPDIR` pointing at a world-writable directory without the sticky bit; tests monkeypatching `os.getuid` inconsistently.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/58d15b3172f0365b. Report an issue: GitHub.