infiniflow/ragflow · error · RuntimeError

Unsupported language for UCloud Agent Sandbox provider: {lan

Error message

Unsupported language for UCloud Agent Sandbox provider: {language}

What it means

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.

Source

Thrown at agent/sandbox/providers/ucloud_agent_sandbox.py:396

            "integration": "ragflow",
        }
        if self.api_url:
            options["api_url"] = self.api_url
        return options

    def _prepare_script(self, sandbox, remote_work_dir: str, language: str, code: str, arguments: dict[str, Any]) -> tuple[str, str]:
        """Wrap user code, upload it, and return its path and executable."""
        args_json = json.dumps(arguments, ensure_ascii=False)
        if language == "python":
            script_name = "main.py"
            script_content = build_python_wrapper(code, args_json)
            executable = "python3"
        elif language == "nodejs":
            script_name = "main.js"
            script_content = build_javascript_wrapper(code, args_json)
            executable = "node"
        else:
            raise RuntimeError(f"Unsupported language for UCloud Agent Sandbox provider: {language}")
        script_path = posixpath.join(remote_work_dir, script_name)
        sandbox.files.write(script_path, script_content, request_timeout=self.timeout)
        return script_path, executable

    def _validate_output_size(self, stdout: str, stderr: str) -> None:
        """Reject combined standard output that exceeds the configured limit."""
        output_size = len(stdout.encode("utf-8")) + len(stderr.encode("utf-8"))
        if output_size > self.max_output_bytes:
            raise RuntimeError(f"UCloud Agent Sandbox execution output exceeded {self.max_output_bytes} bytes.")

    def _collect_artifacts(self, sandbox, artifacts_dir: str) -> list[dict[str, Any]]:
        """Collect allowed files from the execution artifact directory."""
        artifacts: list[dict[str, Any]] = []
        self._collect_artifacts_recursive(sandbox, artifacts_dir, "", artifacts, depth=0)
        return artifacts

    def _collect_artifacts_recursive(self, sandbox, current_dir: str, relative_dir: str, artifacts: list[dict[str, Any]], depth: int) -> None:
        """Traverse artifact directories while enforcing type, size, and depth limits."""

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Pass only "python" or "nodejs" through to execute (normalize at your boundary).
  2. 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.
  3. Keep the two language sets in sync — extract a shared SUPPORTED_LANGUAGES constant in a patch.
  4. Report upstream if you hit it via public APIs only, since it indicates inconsistent provider state.

Example fix

# before (fork added 'ts' to the create_instance whitelist but not here)
provider.execute(inst, code, language="ts")  # RuntimeError in _prepare_script

# after
provider.execute(inst, code, language="nodejs")
Defensive patterns

Strategy: type-guard

Validate before calling

lang = str(language).strip().lower()
if lang not in {"python", "nodejs"}:
    raise ValueError(f"Unsupported language {language!r}")
result = provider.execute(instance_id, code, language=lang)

Type guard

def is_supported_ucloud_language(language: str) -> bool:
    return str(language).strip().lower() in {"python", "nodejs"}

Try / catch

try:
    result = provider.execute(instance_id, code, language=language)
except RuntimeError as e:
    if "Unsupported language" in str(e):
        raise ValueError(f"Bad language config: {language!r}") from e
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/670d38b0cbca5782. Report an issue: GitHub.