{"record":{"id":"9f742f76eb1eb852","repo":"NaiboWang/EasySpider","slug":"function-call-timed-out","errorCode":null,"errorMessage":"function call timed out","messagePattern":"function call timed out","errorType":"exception","errorClass":"TimeoutError","httpStatus":null,"severity":"error","filePath":"ExecuteStage/undetected_chromedriver_ES/devtool.py","lineNumber":86,"sourceCode":"    @classmethod\n    def __init_subclass__(cls, **kwargs):\n        cls._store = {}\n\n    def _normalize_strings(self):\n        for k, v in self.copy().items():\n            if isinstance(v, (str)):\n                self[k] = v.strip()\n\n\ndef timeout(seconds=3, on_timeout: Optional[Callable[[callable], Any]] = None):\n    def wrapper(func):\n        @wraps(func)\n        def wrapped(*args, **kwargs):\n            def function_reached_timeout():\n                if on_timeout:\n                    on_timeout(func)\n                else:\n                    raise TimeoutError(\"function call timed out\")\n\n            t = threading.Timer(interval=seconds, function=function_reached_timeout)\n            t.start()\n            try:\n                return func(*args, **kwargs)\n            except:\n                t.cancel()\n                raise\n            finally:\n                t.cancel()\n\n        return wrapped\n\n    return wrapper\n\n\ndef test():\n    import sys, os","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/NaiboWang/EasySpider/blob/191bd6d7547bb397e4c579dd2c70ae835be3f512/ExecuteStage/undetected_chromedriver_ES/devtool.py#L68-L104","documentation":"Raised as TimeoutError by the `timeout` decorator in ExecuteStage/undetected_chromedriver_ES/devtool.py:86 when a decorated function has not returned within `seconds` (default 3). IMPORTANT threading caveat: the timer callback runs in a separate threading.Timer thread, so the TimeoutError is raised in THAT thread, not in the caller's thread which is still executing func. Unless the caller also surfaces timer-thread exceptions (e.g. via a shared queue/future), the exception may be logged but not actually interrupt the running call.","triggerScenarios":"A function decorated with @timeout(seconds=N) (or called via the decorator factory with on_timeout=None) runs longer than N seconds; the Timer fires function_reached_timeout() which raises TimeoutError('function call timed out'). If on_timeout is provided it is called instead.","commonSituations":"CDP log polling (driver.get_log) blocks because the driver service is unresponsive; network hang talking to chromedriver; the decorated function waits on an event that never arrives; default 3s is too short for slow pages.","solutions":["Increase the seconds argument to a value that comfortably exceeds the slowest expected run.","Pass an on_timeout callback to degrade gracefully instead of raising (e.g. return a sentinel / log and skip).","Diagnose and fix the underlying hang (driver service health, network, deadlocked event loop).","Be aware the TimeoutError fires in the timer thread; if you need to actually cancel the call, run func in a subprocess or use a cancelable primitive instead of this decorator."],"exampleFix":"# before\n@timeout(seconds=3)\ndef poll(driver):\n    return driver.get_log('performance')\n\n# after - longer window + graceful callback\n@timeout(seconds=15, on_timeout=lambda fn: [])\ndef poll(driver):\n    return driver.get_log('performance')","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from devtool import timeout  # or wherever imported\ntry:\n    result = poll(driver)\nexcept TimeoutError as e:\n    if 'function call timed out' in str(e):\n        result = []  # or retry / log\n    else:\n        raise","preventionTips":["Profile decorated functions to pick a realistic timeout, not the 3s default.","Provide an on_timeout callback for any decorator guarding I/O that can legitimately stall.","Do not assume the TimeoutError cancels the in-flight call - it fires on a different thread."],"tags":["undetected-chromedriver","timeout","threading","python"],"backgroundTag":null,"analyzedSha":"191bd6d7547bb397e4c579dd2c70ae835be3f512","analyzedAt":"2026-08-13T03:11:17.041Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}