{"record":{"id":"1eb4e945df24402e","repo":"langchain-ai/deepagents","slug":"suffix-must-be-empty-or-a-short-extension-such-as","errorCode":null,"errorMessage":"suffix must be empty or a short extension such as .md","messagePattern":"suffix must be empty or a short extension such as \\.md","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/auto_mode.py","lineNumber":1019,"sourceCode":"\ndef _current_temp_artifacts(\n    state: Mapping[str, object], runtime: object, messages: Sequence[object]\n) -> dict[str, AutoTempArtifact]:\n    thread_key = _thread_key(runtime)\n    turn_id = _latest_turn_id(messages)\n    if thread_key is None or turn_id is None:\n        return {}\n    return {\n        file_path: artifact\n        for file_path, artifact in _active_temp_artifacts(state).items()\n        if artifact[\"thread_key\"] == thread_key and artifact[\"turn_id\"] == turn_id\n    }\n\n\ndef _validate_temp_artifact_suffix(suffix: str) -> str:\n    if not _TEMP_ARTIFACT_SUFFIX_RE.fullmatch(suffix):\n        msg = \"suffix must be empty or a short extension such as .md\"\n        raise ValueError(msg)\n    return suffix\n\n\ndef _write_temp_artifact_bytes(file_descriptor: int, data: bytes) -> os.stat_result:\n    remaining = memoryview(data)\n    while remaining:\n        written = os.write(file_descriptor, remaining)\n        if written <= 0:\n            msg = \"could not write the complete temporary artifact\"\n            raise OSError(msg)\n        remaining = remaining[written:]\n    return os.fstat(file_descriptor)\n\n\ndef _allocate_temp_artifact(\n    content: str,\n    suffix: str,\n    *,","sourceCodeStart":1001,"sourceCodeEnd":1037,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/auto_mode.py#L1001-L1037","documentation":"`_validate_temp_artifact_suffix` checks the requested suffix against `_TEMP_ARTIFACT_SUFFIX_RE` (empty string or a short file extension like \".md\") and raises `ValueError` if it doesn't match. This is called by `create_temp_artifact` to keep temp artifact filenames safe and predictable and to prevent path tricks via crafted suffixes.","triggerScenarios":"Calling create_temp_artifact(..., suffix=...) with a value failing the regex: multi-part or long extensions (\".tar.gz\", \".markdown\"), strings with slashes or dots in the wrong place (\"/etc\", \"a.md\"), or a suffix lacking a leading dot when one is required.","commonSituations":"Deriving the suffix from a user-supplied filename without normalizing it to a short extension; passing an entire filename as the suffix; joining a directory path into the suffix; passing None where the regex expects a string.","solutions":["Pass an empty string or a short single extension with a leading dot, e.g. suffix=\".md\".","Normalize input filenames first: take only the final extension and lowercase it (pathlib.Path(name).suffix).","Reject or strip directory components and multi-part extensions before calling.","Catch ValueError to fall back to the default empty suffix if the original is unusable."],"exampleFix":"// before\ncreate_temp_artifact(name, suffix=filename)  # suffix=\"report.tar.gz\" -> ValueError\n// after\nsuffix = pathlib.Path(filename).suffix.lower()\nif len(suffix) > 5:\n    suffix = \"\"\ncreate_temp_artifact(name, suffix=suffix)","handlingStrategy":"validation","validationCode":"import re\n_SUFFIX_OK = re.compile(r\"^(\\.[A-Za-z0-9]+)?$\")\ndef safe_suffix(value: str | None) -> str:\n    s = value or \"\"\n    if not _SUFFIX_OK.fullmatch(s) or len(s) > 5:\n        raise UsageError(f\"unsupported suffix {s!r}; use '' or a short extension like '.md'\")\n    return s\n# call site\ncreate_temp_artifact(name, suffix=safe_suffix(user_input))","typeGuard":"def _is_safe_suffix(value: object) -> TypeGuard[str]:\n    return isinstance(value, str) and re.fullmatch(r\"(\\.[A-Za-z0-9]+)?\", value) is not None","tryCatchPattern":"try:\n    path = create_temp_artifact(name, suffix=user_suffix)\nexcept ValueError:\n    path = create_temp_artifact(name, suffix=\"\")  # fall back to default","preventionTips":["Derive suffixes with pathlib.Path(filename).suffix instead of passing whole filenames.","Whitelist allowed extensions (.md, .txt, .json) in your own UI before calling create_temp_artifact.","Strip any path components from user-supplied values; never embed '/' in a suffix.","Cap extension length and normalize case before passing through."],"tags":["validation","filesystem","temp-files","input-error"],"backgroundTag":"invalid-filename-suffix","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}