{"record":{"id":"7a88848c997cd93b","repo":"infiniflow/ragflow","slug":"execution-timeout-must-be-greater-than-0-seconds","errorCode":null,"errorMessage":"Execution timeout must be greater than 0 seconds, got {requested_timeout}.","messagePattern":"Execution timeout must be greater than 0 seconds, got (.+?)\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/sandbox/providers/local.py","lineNumber":124,"sourceCode":"\n    def execute_code(\n        self,\n        instance_id: str,\n        code: str,\n        language: str,\n        timeout: int = 10,\n        arguments: Optional[Dict[str, Any]] = None,\n    ) -> ExecutionResult:\n        if not self._initialized:\n            raise RuntimeError(\"Provider not initialized. Call initialize() first.\")\n\n        normalized_lang = self._normalize_language(language)\n        instance_dir = self._instances[instance_id]\n        args_json = json.dumps(arguments or {}, ensure_ascii=False)\n        command, script_path = self._prepare_script(instance_dir, normalized_lang, code, args_json)\n        requested_timeout = self.timeout if timeout is None else int(timeout)\n        if requested_timeout <= 0:\n            raise RuntimeError(f\"Execution timeout must be greater than 0 seconds, got {requested_timeout}.\")\n        exec_timeout = min(requested_timeout, self.timeout)\n\n        start_time = time.time()\n        process = subprocess.Popen(\n            command,\n            cwd=instance_dir,\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n            encoding=\"utf-8\",\n            errors=\"replace\",\n            env=self._build_child_env(instance_dir),\n            preexec_fn=self._limit_child_process if os.name == \"posix\" else None,\n            start_new_session=os.name == \"posix\",\n        )\n\n        try:\n            stdout, stderr = process.communicate(timeout=exec_timeout)","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/sandbox/providers/local.py#L106-L142","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a positive timeout (or None to use the provider default) to execute_code.","Validate/clamp user-supplied timeouts at the API boundary before they reach the provider.","Fix the provider default timeout in config if it is 0 or negative."],"exampleFix":"# before\nprovider.execute_code(instance_id, code, \"python\", timeout=0)\n\n# after: normalize 'unset' to the provider default and clamp\nsafe_timeout = timeout if timeout and int(timeout) > 0 else None\nprovider.execute_code(instance_id, code, \"python\", timeout=safe_timeout)","handlingStrategy":"validation","validationCode":"def normalize_timeout(t):\n    \"\"\"Map 'unset'/invalid to None so the provider default applies.\"\"\"\n    if t is None:\n        return None\n    t = int(t)\n    return t if t > 0 else None\n\nprovider.execute_code(instance_id, code, \"python\", timeout=normalize_timeout(user_timeout))","typeGuard":"def is_positive_timeout(t) -> bool:\n    return t is None or (isinstance(t, int) and t > 0)","tryCatchPattern":"try:\n    provider.execute_code(instance_id, code, \"python\", timeout=timeout)\nexcept RuntimeError as e:\n    if \"must be greater than 0\" in str(e):\n        provider.execute_code(instance_id, code, \"python\", timeout=None)  # provider default\n    else:\n        raise","preventionTips":["Validate user-supplied timeouts at the API boundary; clamp instead of forwarding.","Do not use 0 to mean 'no timeout' — pass None for the provider default.","Keep the provider's configured default timeout positive."],"tags":["validation","timeout","local","arguments"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}