{"record":{"id":"f0a5c531e7dda0c1","repo":"infiniflow/ragflow","slug":"unsupported-artifact-type-relative-path-f0a5c5","errorCode":null,"errorMessage":"Unsupported artifact type: {relative_path}","messagePattern":"Unsupported artifact type: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/sandbox/providers/ucloud_agent_sandbox.py","lineNumber":436,"sourceCode":"        try:\n            entries = sandbox.files.list(current_dir, depth=1, request_timeout=self.timeout)\n        except sdk.FileNotFoundException:\n            return\n        for entry in sorted(entries, key=lambda item: item.path):\n            name = posixpath.basename(entry.path)\n            relative_path = posixpath.join(relative_dir, name) if relative_dir else name\n            if entry.symlink_target is not None:\n                raise RuntimeError(f\"Artifact symlinks are not allowed: {relative_path}\")\n            if entry.type == sdk.FileType.DIR:\n                self._collect_artifacts_recursive(sandbox, entry.path, relative_path, artifacts, depth + 1)\n                continue\n            if len(artifacts) >= self.max_artifacts:\n                raise RuntimeError(f\"UCloud Agent Sandbox execution produced more than {self.max_artifacts} artifacts.\")\n            if entry.size > self.max_artifact_bytes:\n                raise RuntimeError(f\"Artifact exceeds {self.max_artifact_bytes} bytes: {relative_path}\")\n            extension = os.path.splitext(name)[1].lower()\n            if extension not in ALLOWED_ARTIFACT_EXTENSIONS:\n                raise RuntimeError(f\"Unsupported artifact type: {relative_path}\")\n            content = bytes(sandbox.files.read(entry.path, format=\"bytes\", request_timeout=self.timeout))\n            artifacts.append(\n                {\n                    \"name\": relative_path,\n                    \"content_b64\": base64.b64encode(content).decode(\"ascii\"),\n                    \"mime_type\": mimetypes.guess_type(name)[0] or \"application/octet-stream\",\n                    \"size\": entry.size,\n                }\n            )\n\n    def _safe_kill(self, sandbox) -> None:\n        \"\"\"Best-effort terminate a remote sandbox during cleanup.\"\"\"\n        try:\n            sandbox.kill(request_timeout=self.timeout)\n        except Exception as exc:  # noqa: BLE001 - cleanup is deliberately best-effort\n            logger.warning(\"Failed to kill UCloud Agent Sandbox %s: %s\", sandbox.sandbox_id, exc)\n\n    @staticmethod","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/sandbox/providers/ucloud_agent_sandbox.py#L418-L454","documentation":"Raised during artifact collection when a file's lowercase extension is not in ALLOWED_ARTIFACT_EXTENSIONS. Only a whitelist of file types may be returned as artifacts; anything else (executables, unknown or missing extensions) aborts collection.","triggerScenarios":"Executed code writing files with extensions outside the allowlist — e.g. .exe, .sh, .pyc, .so, or extensionless files — into the artifacts directory.","commonSituations":"Build-style user code emitting binaries or scripts; tools writing dotfiles/extensionless temp files; LLM-generated code saving output with a creative filename the allowlist never anticipated.","solutions":["Emit artifacts in allowed common formats (e.g. .txt/.json/.png/.csv — check ALLOWED_ARTIFACT_EXTENSIONS in the module) and rename outputs accordingly.","Keep non-artifact intermediate files outside the artifacts directory.","If a type is legitimately needed, extend ALLOWED_ARTIFACT_EXTENSIONS in a patch after reviewing the security implications.","Catch the RuntimeError to surface 'unsupported artifact type' clearly to the agent/user."],"exampleFix":"# before\nopen(\"artifacts/run.sh\", \"w\").write(script)  # .sh not allowlisted -> RuntimeError\n\n# after\nopen(\"artifacts/run_script.txt\", \"w\").write(script)","handlingStrategy":"validation","validationCode":"from agent.sandbox.providers.ucloud_agent_sandbox import ALLOWED_ARTIFACT_EXTENSIONS\nimport os\n\noutputs = [f for f in candidate_files]\nbad = [f for f in outputs if os.path.splitext(f)[1].lower() not in ALLOWED_ARTIFACT_EXTENSIONS]\nif bad:\n    raise ValueError(f\"artifact extensions not allowed: {bad}\")","typeGuard":"def has_allowed_artifact_extensions(filenames: list[str], allowed: set[str]) -> bool:\n    return all(os.path.splitext(f)[1].lower() in allowed for f in filenames)","tryCatchPattern":"try:\n    result = provider.execute(inst, code)\nexcept RuntimeError as e:\n    if \"Unsupported artifact type\" in str(e):\n        result = provider.execute(inst, rename_artifacts_to_allowed(code))\n    else:\n        raise","preventionTips":["Standardize generated outputs on allowlisted extensions (.txt/.json/.csv/.png etc.) — check ALLOWED_ARTIFACT_EXTENSIONS before dispatch.","Keep intermediate/build files outside the artifacts directory; they commonly carry exotic extensions.","If extending the allowlist in a fork, review executable types (.sh/.exe/.so) carefully — they are excluded for safety."],"tags":["artifacts","ucloud","sandbox","file-type","allowlist"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}