infiniflow/ragflow · error · RuntimeError

Execution timeout must be greater than 0 seconds, got {reque

Error message

Execution timeout must be greater than 0 seconds, got {requested_timeout}.

What it means

Explicit argument validation in LocalSandboxProvider.execute_code: the effective requested timeout (the `timeout` argument, or the provider default when None) must be a positive integer. Zero or negative values are rejected before any subprocess is spawned.

Source

Thrown at agent/sandbox/providers/local.py:124

    def execute_code(
        self,
        instance_id: str,
        code: str,
        language: str,
        timeout: int = 10,
        arguments: Optional[Dict[str, Any]] = None,
    ) -> ExecutionResult:
        if not self._initialized:
            raise RuntimeError("Provider not initialized. Call initialize() first.")

        normalized_lang = self._normalize_language(language)
        instance_dir = self._instances[instance_id]
        args_json = json.dumps(arguments or {}, ensure_ascii=False)
        command, script_path = self._prepare_script(instance_dir, normalized_lang, code, args_json)
        requested_timeout = self.timeout if timeout is None else int(timeout)
        if requested_timeout <= 0:
            raise RuntimeError(f"Execution timeout must be greater than 0 seconds, got {requested_timeout}.")
        exec_timeout = min(requested_timeout, self.timeout)

        start_time = time.time()
        process = subprocess.Popen(
            command,
            cwd=instance_dir,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            encoding="utf-8",
            errors="replace",
            env=self._build_child_env(instance_dir),
            preexec_fn=self._limit_child_process if os.name == "posix" else None,
            start_new_session=os.name == "posix",
        )

        try:
            stdout, stderr = process.communicate(timeout=exec_timeout)

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Pass a positive timeout (or None to use the provider default) to execute_code.
  2. Validate/clamp user-supplied timeouts at the API boundary before they reach the provider.
  3. Fix the provider default timeout in config if it is 0 or negative.

Example fix

# before
provider.execute_code(instance_id, code, "python", timeout=0)

# after: normalize 'unset' to the provider default and clamp
safe_timeout = timeout if timeout and int(timeout) > 0 else None
provider.execute_code(instance_id, code, "python", timeout=safe_timeout)
Defensive patterns

Strategy: validation

Validate before calling

def normalize_timeout(t):
    """Map 'unset'/invalid to None so the provider default applies."""
    if t is None:
        return None
    t = int(t)
    return t if t > 0 else None

provider.execute_code(instance_id, code, "python", timeout=normalize_timeout(user_timeout))

Type guard

def is_positive_timeout(t) -> bool:
    return t is None or (isinstance(t, int) and t > 0)

Try / catch

try:
    provider.execute_code(instance_id, code, "python", timeout=timeout)
except RuntimeError as e:
    if "must be greater than 0" in str(e):
        provider.execute_code(instance_id, code, "python", timeout=None)  # provider default
    else:
        raise

Prevention

When it happens

Trigger: Calling execute_code with timeout=0 or a negative number; config setting the provider default timeout to 0 so `self.timeout` is used when timeout=None; passing a value coerced from bad user input.

Common situations: Upstream code forwarding a user-supplied timeout without validation (e.g., 0 used as 'unset'); YAML config with timeout: 0 meaning 'no limit' but interpreted literally.

Understand the failure class

Related errors


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