{"record":{"id":"b67c24b3af901a09","repo":"infiniflow/ragflow","slug":"unsupported-artifact-entry-relative-path","errorCode":null,"errorMessage":"Unsupported artifact entry: {relative_path}","messagePattern":"Unsupported artifact entry: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/sandbox/providers/ssh.py","lineNumber":646,"sourceCode":"            return\n\n        for entry in sorted(entries, key=lambda item: item.filename):\n            name = entry.filename\n            remote_path = posixpath.join(current_dir, name)\n            relative_path = posixpath.join(relative_dir, name) if relative_dir else name\n            mode = entry.st_mode\n            if mode is None:\n                mode = sftp.lstat(remote_path).st_mode\n            if mode is None:\n                raise RuntimeError(f\"Unable to determine artifact entry type: {relative_path}\")\n\n            if stat.S_ISLNK(mode):\n                raise RuntimeError(f\"Artifact symlinks are not allowed: {relative_path}\")\n            if stat.S_ISDIR(mode):\n                self._collect_artifacts_recursive(sftp, remote_path, relative_path, artifacts)\n                continue\n            if not stat.S_ISREG(mode):\n                raise RuntimeError(f\"Unsupported artifact entry: {relative_path}\")\n\n            if len(artifacts) >= self.max_artifacts:\n                raise RuntimeError(f\"SSH execution produced more than {self.max_artifacts} artifacts.\")\n\n            size = int(entry.st_size or 0)\n            if size > self.max_artifact_bytes:\n                raise RuntimeError(f\"Artifact exceeds {self.max_artifact_bytes} bytes: {relative_path}\")\n\n            ext = os.path.splitext(name)[1].lower()\n            if ext not in ALLOWED_ARTIFACT_EXTENSIONS:\n                raise RuntimeError(f\"Unsupported artifact type: {relative_path}\")\n\n            with sftp.file(remote_path, \"rb\") as artifact_file:\n                content = artifact_file.read()\n\n            artifacts.append(\n                {\n                    \"name\": relative_path,","sourceCodeStart":628,"sourceCodeEnd":664,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/sandbox/providers/ssh.py#L628-L664","documentation":"Raised as RuntimeError when an artifacts-dir entry is neither a symlink, directory, nor regular file (stat.S_ISREG fails) — e.g. FIFOs, sockets, device nodes. The collector can only package regular files, and special entries could hang a read (FIFO) or escape the size/extension checks, so they abort collection. Mode comes from listdir_attr with an lstat fallback.","triggerScenarios":"Sandboxed code mkfifo()-ing a file in the artifacts directory; a crashed process leaving a unix socket in the workspace; /dev or other special nodes bind-mounted into the workspace.","commonSituations":"Generated code using multiprocessing (which creates semaphore/socket files) with artifacts dir = working dir; debug tooling leaving FIFOs; misconfigured containers mounting device nodes under work_dir.","solutions":["Point artifact output at a dedicated clean directory; keep runtime scratch (sockets, fifos) outside it","Clean special files before finishing: os.remove() any FIFOs/sockets created by the code","Configure work_dir so no special nodes from the system fall under the artifacts tree"],"exampleFix":"# before (sandboxed code)\nos.mkfifo('artifacts/pipe')  # collection later aborts\n\n# after (sandboxed code)\nimport multiprocessing\nmp.set_start_method('fork')  # or keep sockets out of the artifacts dir\nopen('artifacts/result.txt', 'w').write('done')","handlingStrategy":"try-catch","validationCode":"# inside sandboxed code, before returning\nimport os, stat\nfor root, _, files in os.walk(artifacts_dir):\n    for f in files:\n        p = os.path.join(root, f)\n        if not stat.S_ISREG(os.lstat(p).st_mode):\n            os.remove(p)","typeGuard":null,"tryCatchPattern":"try:\n    artifacts = provider.collect_artifacts(instance_id, artifacts_dir)\nexcept RuntimeError as e:\n    if \"Unsupported artifact entry\" in str(e):\n        log.warning(\"special file in artifacts dir; cleaning and retrying\")\n        raise","preventionTips":["Keep multiprocessing/socket scratch files outside the artifacts directory","Remove FIFOs/sockets before the sandboxed code returns","Don't mount device nodes or special filesystems under work_dir"],"tags":["artifacts","filesystem","special-files","ssh"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}