{"record":{"id":"670d38b0cbca5782","repo":"infiniflow/ragflow","slug":"unsupported-language-for-ucloud-agent-sandbox-prov-670d38","errorCode":null,"errorMessage":"Unsupported language for UCloud Agent Sandbox provider: {language}","messagePattern":"Unsupported language for UCloud Agent Sandbox provider: (.+?)","errorType":"validation","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/sandbox/providers/ucloud_agent_sandbox.py","lineNumber":396,"sourceCode":"            \"integration\": \"ragflow\",\n        }\n        if self.api_url:\n            options[\"api_url\"] = self.api_url\n        return options\n\n    def _prepare_script(self, sandbox, remote_work_dir: str, language: str, code: str, arguments: dict[str, Any]) -> tuple[str, str]:\n        \"\"\"Wrap user code, upload it, and return its path and executable.\"\"\"\n        args_json = json.dumps(arguments, ensure_ascii=False)\n        if language == \"python\":\n            script_name = \"main.py\"\n            script_content = build_python_wrapper(code, args_json)\n            executable = \"python3\"\n        elif language == \"nodejs\":\n            script_name = \"main.js\"\n            script_content = build_javascript_wrapper(code, args_json)\n            executable = \"node\"\n        else:\n            raise RuntimeError(f\"Unsupported language for UCloud Agent Sandbox provider: {language}\")\n        script_path = posixpath.join(remote_work_dir, script_name)\n        sandbox.files.write(script_path, script_content, request_timeout=self.timeout)\n        return script_path, executable\n\n    def _validate_output_size(self, stdout: str, stderr: str) -> None:\n        \"\"\"Reject combined standard output that exceeds the configured limit.\"\"\"\n        output_size = len(stdout.encode(\"utf-8\")) + len(stderr.encode(\"utf-8\"))\n        if output_size > self.max_output_bytes:\n            raise RuntimeError(f\"UCloud Agent Sandbox execution output exceeded {self.max_output_bytes} bytes.\")\n\n    def _collect_artifacts(self, sandbox, artifacts_dir: str) -> list[dict[str, Any]]:\n        \"\"\"Collect allowed files from the execution artifact directory.\"\"\"\n        artifacts: list[dict[str, Any]] = []\n        self._collect_artifacts_recursive(sandbox, artifacts_dir, \"\", artifacts, depth=0)\n        return artifacts\n\n    def _collect_artifacts_recursive(self, sandbox, current_dir: str, relative_dir: str, artifacts: list[dict[str, Any]], depth: int) -> None:\n        \"\"\"Traverse artifact directories while enforcing type, size, and depth limits.\"\"\"","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/sandbox/providers/ucloud_agent_sandbox.py#L378-L414","documentation":"Defensive guard inside `_prepare_script`: after `execute()` normalized the language, the wrapper builder only handles exactly \"python\" and \"nodejs\". If a language slips past the create_instance whitelist (e.g. via a divergent normalization path or a directly-injected instance state), this RuntimeError fires. In practice it should be unreachable for public callers because create_instance already rejects the same set.","triggerScenarios":"Calling the internal execute path with a language string that normalize does not map to python/nodejs — most realistically when instance metadata or language is supplied by custom code that bypasses create_instance validation.","commonSituations":"Custom orchestration storing its own language field on the instance dict; refactors that change _normalize_language (adding an alias) without updating _prepare_script; test harnesses calling _prepare_script directly.","solutions":["Pass only \"python\" or \"nodejs\" through to execute (normalize at your boundary).","If maintaining a fork that adds languages, add the branch in _prepare_script (script_name, wrapper builder, executable) together with the whitelist in create_instance.","Keep the two language sets in sync — extract a shared SUPPORTED_LANGUAGES constant in a patch.","Report upstream if you hit it via public APIs only, since it indicates inconsistent provider state."],"exampleFix":"# before (fork added 'ts' to the create_instance whitelist but not here)\nprovider.execute(inst, code, language=\"ts\")  # RuntimeError in _prepare_script\n\n# after\nprovider.execute(inst, code, language=\"nodejs\")","handlingStrategy":"type-guard","validationCode":"lang = str(language).strip().lower()\nif lang not in {\"python\", \"nodejs\"}:\n    raise ValueError(f\"Unsupported language {language!r}\")\nresult = provider.execute(instance_id, code, language=lang)","typeGuard":"def is_supported_ucloud_language(language: str) -> bool:\n    return str(language).strip().lower() in {\"python\", \"nodejs\"}","tryCatchPattern":"try:\n    result = provider.execute(instance_id, code, language=language)\nexcept RuntimeError as e:\n    if \"Unsupported language\" in str(e):\n        raise ValueError(f\"Bad language config: {language!r}\") from e\n    raise","preventionTips":["Only use languages accepted by create_instance; keep one shared whitelist constant for both layers.","If you fork the provider to add languages, update create_instance, _normalize_language, and _prepare_script together.","Treat hitting this via public APIs as a bug report — the two validation sets have drifted."],"tags":["sandbox","ucloud","language","internal","invariant"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}