{"record":{"id":"0447813fa1f2e266","repo":"langchain-ai/deepagents","slug":"temporary-artifact-identity-changed","errorCode":null,"errorMessage":"temporary artifact identity changed","messagePattern":"temporary artifact identity changed","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/auto_mode.py","lineNumber":1124,"sourceCode":"                )\n            ]\n        }\n    )\n\n\ndef _delete_temp_artifact_file(artifact: AutoTempArtifact) -> None:\n    file_path = Path(artifact[\"file_path\"])\n    if not file_path.name.startswith(_TEMP_ARTIFACT_PREFIX):\n        msg = \"temporary artifact provenance is invalid\"\n        raise OSError(msg)\n    file_stat = file_path.lstat()\n    if (\n        not stat.S_ISREG(file_stat.st_mode)\n        or file_stat.st_dev != artifact[\"file_device\"]\n        or file_stat.st_ino != artifact[\"file_inode\"]\n    ):\n        msg = \"temporary artifact identity changed\"\n        raise OSError(msg)\n    file_path.unlink()\n\n\ndef _summarize_value(key: str, value: object, *, depth: int = 0) -> object:\n    if depth >= _MAX_ARGUMENT_DEPTH:\n        return \"[nested value omitted]\"\n    if _SECRET_KEY_RE.search(key):\n        return \"[redacted credential value]\"\n    if key.lower() in {\"content\", \"new_string\", \"old_string\", \"new_str\"} and isinstance(\n        value, str\n    ):\n        return {\"character_count\": len(value), \"content_omitted\": True}\n    if isinstance(value, str):\n        return value[:4000]\n    if isinstance(value, Mapping):\n        return {\n            str(child_key): _summarize_value(\n                str(child_key), child_value, depth=depth + 1","sourceCodeStart":1106,"sourceCodeEnd":1142,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/auto_mode.py#L1106-L1142","documentation":"Raised by `_delete_temp_artifact_file` when an `lstat` of the artifact's path does not match the identity recorded at creation: the file is no longer a regular file, or its `st_dev`/`st_ino` differ from the `file_device`/`file_inode` stored in the `AutoTempArtifact`. The library throws this to prevent a symlink-swap or replacement race from causing it to unlink the wrong file.","triggerScenarios":"Calling `delete_temp_artifact` after the temp file was deleted and recreated, replaced by a symlink or different inode, or moved/renamed — any change of device or inode between `create_temp_artifact` and the delete call.","commonSituations":"Another process or a cleanup daemon (`tmpwatch`, `systemd-tmpfiles`) removing and re-creating files in the temp dir; tests reusing artifact records across temp dirs; the same artifact record being deleted twice, where the second delete fails because the original inode is gone; an attacker swapping the file (the check exists for this).","solutions":["Retry the whole flow: re-create the artifact with `create_temp_artifact` rather than reusing the stale record","Check for temp-file cleaners (`systemd-tmpfiles`, `tmpwatch`, cron scripts) racing the agent and exclude the prefix or shorten the artifact lifetime","If the file is legitimately already gone, treat the deletion as done and drop the stale artifact record from state","Never delete the same artifact record twice — track the returned allocation lifecycle"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import os, stat\nfrom pathlib import Path\n\ndef artifact_identity_intact(artifact) -> bool:\n    try:\n        st = Path(artifact[\"file_path\"]).lstat()\n    except FileNotFoundError:\n        return False\n    return stat.S_ISREG(st.st_mode) and st.st_dev == artifact[\"file_device\"] and st.st_ino == artifact[\"file_inode\"]","typeGuard":null,"tryCatchPattern":"try:\n    delete_temp_artifact(artifact)\nexcept OSError as exc:\n    if \"identity changed\" in str(exc):\n        discard_stale_record()  # file already gone or replaced; nothing safe to unlink\n    else:\n        raise","preventionTips":["Delete artifacts promptly in the same turn they are created","Exclude the library's temp prefix from tmpfile cleaners (systemd-tmpfiles, tmpwatch)","Never delete the same artifact record twice","Avoid moving or re-creating files under the recorded artifact path"],"tags":["filesystem","race-condition","security","temp-file","inode"],"backgroundTag":"temp-file-identity-changed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}