{"record":{"id":"e3b38184067e328a","repo":"infiniflow/ragflow","slug":"local-execution-produced-more-than-self-max-artif","errorCode":null,"errorMessage":"Local execution produced more than {self.max_artifacts} artifacts.","messagePattern":"Local execution produced more than (.+?) artifacts\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/sandbox/providers/local.py","lineNumber":327,"sourceCode":"        resource.setrlimit(kind, (limit, limit))\n\n    def _validate_output_size(self, stdout: str, stderr: str) -> None:\n        output_size = len((stdout or \"\").encode(\"utf-8\")) + len((stderr or \"\").encode(\"utf-8\"))\n        if output_size > self.max_output_bytes:\n            raise RuntimeError(f\"Local execution output exceeded {self.max_output_bytes} bytes.\")\n\n    def _collect_artifacts(self, artifacts_dir: Path) -> list[dict[str, Any]]:\n        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","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/sandbox/providers/local.py#L309-L345","documentation":"Raised by LocalProvider._collect_artifacts() when the artifacts directory contains more collectible files than the configured max_artifacts cap (default 20). The check fires when appending the (max+1)-th file — directories are skipped and invalid entries fail earlier, so this counts regular files with allowed handling up to that point. The whole run fails; no partial artifact list is returned.","triggerScenarios":"Executed code writing 21+ files into artifacts/ with max_artifacts left at default; lowering 'max_artifacts' at initialize() while generated code writes many plots/CSV shards; batch jobs emitting one file per iteration.","commonSituations":"LLM-generated loops saving a figure per step; sharding a dataset into many part files; a low cap configured to keep responses small while the code has no notion of the cap.","solutions":["Reduce file count in the executed code: aggregate into one archive or single CSV/JSON, or keep only the top-N outputs.","Raise 'max_artifacts' at initialize() if many files are expected (schema max 100).","Set 'max_artifacts': 0 and skip artifact collection if artifacts are not needed — note this check only triggers when collection runs with cap 0 and any file exists, so also ensure artifacts/ stays empty.","Pass the cap into the code-generation prompt so the model knows the budget."],"exampleFix":"# before (executed code)\nfor i in range(50):\n    df[i].to_csv(f'artifacts/part_{i}.csv')\n\n# after (executed code)\nimport pandas as pd\npd.concat(df).to_csv('artifacts/all_parts.csv')","handlingStrategy":"validation","validationCode":"# in the executed code, before returning:\n# n = len(list(Path('artifacts').iterdir())); assert n <= MAX_ARTIFACTS","typeGuard":null,"tryCatchPattern":"try:\n    result = provider.execute_code(instance_id, code, \"python\")\nexcept RuntimeError as e:\n    if \"more than\" in str(e) and \"artifacts\" in str(e):\n        raise TooManyArtifacts(str(e)) from e\n    raise","preventionTips":["Aggregate many small outputs into one file in the executed code.","Pass the artifact budget into code-generation prompts.","Set max_artifacts from measured workload needs, not the default, when generating batches of files."],"tags":["sandbox","artifacts","limits","local-provider"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}