{"record":{"id":"22e5be6fc1e4fc09","repo":"infiniflow/ragflow","slug":"unsupported-artifact-type-path-name","errorCode":null,"errorMessage":"Unsupported artifact type: {path.name}","messagePattern":"Unsupported artifact type: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/sandbox/providers/local.py","lineNumber":335,"sourceCode":"        artifacts: list[dict[str, Any]] = []\n        for path in sorted(artifacts_dir.rglob(\"*\")):\n            if path.is_symlink():\n                raise RuntimeError(f\"Artifact symlinks are not allowed: {path.name}\")\n            if path.is_dir():\n                continue\n            if not path.is_file():\n                raise RuntimeError(f\"Unsupported artifact entry: {path.name}\")\n\n            if len(artifacts) >= self.max_artifacts:\n                raise RuntimeError(f\"Local execution produced more than {self.max_artifacts} artifacts.\")\n\n            size = path.stat().st_size\n            if size > self.max_artifact_bytes:\n                raise RuntimeError(f\"Artifact exceeds {self.max_artifact_bytes} bytes: {path.name}\")\n\n            ext = path.suffix.lower()\n            if ext not in ALLOWED_ARTIFACT_EXTENSIONS:\n                raise RuntimeError(f\"Unsupported artifact type: {path.name}\")\n\n            artifacts.append(\n                {\n                    \"name\": path.relative_to(artifacts_dir).as_posix(),\n                    \"content_b64\": base64.b64encode(path.read_bytes()).decode(\"ascii\"),\n                    \"mime_type\": mimetypes.guess_type(path.name)[0] or \"application/octet-stream\",\n                    \"size\": size,\n                }\n            )\n        return artifacts\n\n    @staticmethod\n    def _normalize_language(language: str) -> str:\n        lang_lower = (language or \"python\").lower()\n        if lang_lower in {\"python\", \"python3\"}:\n            return \"python\"\n        if lang_lower in {\"javascript\", \"nodejs\"}:\n            return \"nodejs\"","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/sandbox/providers/local.py#L317-L353","documentation":"Raised by LocalProvider._collect_artifacts() when a collected file's lowercase extension is not in ALLOWED_ARTIFACT_EXTENSIONS ({.csv, .html, .jpeg, .jpg, .json, .pdf, .png, .svg}). Files with any other extension (e.g. .txt, .parquet, .xlsx, .py, extensionless) cause the whole run to fail during artifact collection.","triggerScenarios":"Executed code writing artifacts/plain.txt, results.parquet, model.pkl, or an extensionless file into artifacts/. Case-insensitive: .PNG is fine, .Png fine; .txt is not.","commonSituations":"LLM-generated code writing logs or reports as .txt by habit; dataframe.to_excel producing .xlsx; pickle joblib artifacts; assuming the collector accepts any file.","solutions":["Write artifacts with an allowed extension: rename .txt to .html/.csv/.json as appropriate, save figures as .png/.svg, tables as .csv/.json.","For arbitrary binary payloads, wrap in JSON (base64) or emit a PDF/CSV container.","If you own the deployment and need more types, extend ALLOWED_ARTIFACT_EXTENSIONS in agent/sandbox/providers/local.py — but keep the risk of unbounded types in mind.","Put non-artifact intermediate files outside the artifacts directory (they are not scanned)."],"exampleFix":"# before (executed code)\nPath('artifacts/report.txt').write_text(text)\n\n# after (executed code)\nPath('artifacts/report.html').write_text(f'<pre>{text}</pre>')","handlingStrategy":"type-guard","validationCode":"from agent.sandbox.providers.local import ALLOWED_ARTIFACT_EXTENSIONS\n\ndef has_allowed_artifact_extensions(artifact_names: list[str]) -> bool:\n    from pathlib import Path\n    return all(Path(n).suffix.lower() in ALLOWED_ARTIFACT_EXTENSIONS for n in artifact_names)","typeGuard":"ALLOWED = {'.csv', '.html', '.jpeg', '.jpg', '.json', '.pdf', '.png', '.svg'}\n\ndef is_allowed_artifact_name(name: str) -> bool:\n    \"\"\"True when LocalProvider will collect this artifact filename.\"\"\"\n    from pathlib import Path\n    return Path(name).suffix.lower() in ALLOWED","tryCatchPattern":"try:\n    result = provider.execute_code(instance_id, code, \"python\")\nexcept RuntimeError as e:\n    if \"Unsupported artifact type\" in str(e):\n        raise BadArtifactType(str(e)) from e\n    raise","preventionTips":["Constrain executed code to emit only .csv/.html/.json/.pdf/.png/.svg/.jpg/.jpeg files into artifacts/.","Keep scratch files outside the artifacts directory.","Encode arbitrary text as .html (wrapped in <pre>) or .json instead of .txt."],"tags":["sandbox","artifacts","file-type","local-provider"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}