{"record":{"id":"7edbd2d0a44d611f","repo":"infiniflow/ragflow","slug":"execution-timed-out-after-exec-timeout-seconds","errorCode":null,"errorMessage":"Execution timed out after {exec_timeout} seconds","messagePattern":"Execution timed out after (.+?) seconds","errorType":"exception","errorClass":"TimeoutError","httpStatus":null,"severity":"error","filePath":"agent/sandbox/providers/local.py","lineNumber":149,"sourceCode":"            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)\n        except subprocess.TimeoutExpired:\n            if os.name == \"posix\":\n                os.killpg(process.pid, signal.SIGKILL)\n            else:\n                process.kill()\n            process.communicate()\n            raise TimeoutError(f\"Execution timed out after {exec_timeout} seconds\")\n\n        execution_time = time.time() - start_time\n        self._validate_output_size(stdout, stderr)\n        stdout, structured_result = extract_structured_result(stdout)\n\n        return ExecutionResult(\n            stdout=stdout,\n            stderr=stderr,\n            exit_code=process.returncode,\n            execution_time=execution_time,\n            metadata={\n                \"instance_id\": instance_id,\n                \"language\": normalized_lang,\n                \"script_path\": str(script_path),\n                \"status\": \"ok\" if process.returncode == 0 else \"error\",\n                \"timeout\": exec_timeout,\n                \"artifacts\": self._collect_artifacts(instance_dir / \"artifacts\"),\n                \"result_present\": structured_result.get(\"present\", False),","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/sandbox/providers/local.py#L131-L167","documentation":"Raised as TimeoutError by LocalSandboxProvider when the child process does not finish within exec_timeout (the minimum of the requested timeout and the provider's configured max). On POSIX the whole process group is SIGKILLed via killpg (children spawned with start_new_session), then remaining output is drained before raising.","triggerScenarios":"User code containing infinite loops, deadlocks, or waits longer than exec_timeout; requesting a timeout larger than the provider max (it is clamped down); subprocesses spawned by the user code keeping the pipe open.","commonSituations":"Agent-generated code with unbounded loops; network calls without timeouts inside sandboxed code; forgetting that the provider-level `timeout` config caps every execution.","solutions":["Fix or bound the sandboxed code — add internal timeouts to loops and network calls.","Raise the requested timeout and the provider's configured timeout if the workload legitimately needs longer.","Split long work into multiple execute_code calls, persisting intermediate state in artifacts.","Note the process group is killed, so child processes do not keep the slot busy — the timeout reflects real wall time."],"exampleFix":"# before\nresult = provider.execute_code(instance_id, code, \"python\", timeout=5)  # code sleeps 30s -> TimeoutError\n\n# after: align the timeout with the workload (still capped by provider config)\nresult = provider.execute_code(instance_id, code, \"python\", timeout=60)","handlingStrategy":"try-catch","validationCode":"# Static check on the code string for common unbounded patterns before paying for a run\nimport re\nif re.search(r\"while\\s+True\", code) and \"break\" not in code:\n    raise ValueError(\"Refusing to run unbounded loop without break\")","typeGuard":null,"tryCatchPattern":"try:\n    result = provider.execute_code(instance_id, code, \"python\", timeout=10)\nexcept TimeoutError:\n    logger.warning(\"Sandbox execution hit timeout; instance may hold partial state\")\n    provider.destroy_instance(instance_id)\n    instance = provider.create_instance(\"python\")\n    raise","preventionTips":["Always pass an explicit, workload-appropriate timeout.","Know the provider-level timeout cap — requests above it are clamped down.","Put internal timeouts on network/IO inside sandboxed code.","After a timeout, prefer destroying the instance: partial state from the SIGKILLed run can corrupt later cells."],"tags":["timeout","local","execution","process-management"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}