jumpserver/jumpserver · error · TimeoutError

{name} timed out, wait {timeout}s

Error message

{name} timed out, wait {timeout}s

What it means

Raised by the raise_timeout decorator's signal handler in remote_client.py: each wrapped method arms a SIGALRM timer of self.timeout seconds, and when the ITIMER_REAL deadline expires the handler raises TimeoutError('{name} timed out, wait {timeout}s'). It bounds individual SSH remote operations so they cannot hang forever.

Source

Thrown at apps/libs/ansible/modules_utils/remote_client.py:103

        become_method=dict(type='str', required=False),
        become_user=dict(type='str', required=False),
        become_password=dict(type='str', required=False, no_log=True),
        become_private_key_path=dict(type='str', required=False, no_log=True),

        old_ssh_version=dict(type='bool', default=False, required=False),
        auth_only=dict(type='bool', default=False, required=False),
        fail_on_unknown=dict(type='bool', default=True, required=False),
        change_succeeded=dict(type='bool', default=True, required=False),
    )
    return options


def raise_timeout(name=''):
    def decorate(func):
        @wraps(func)
        def wrapper(self, *args, **kwargs):
            def handler(signum, frame):
                raise TimeoutError(f'{name} timed out, wait {timeout}s')

            timeout = float(getattr(self, 'timeout', 0) or 0)
            can_use_alarm = (
                timeout > 0
                and hasattr(signal, 'SIGALRM')
                and hasattr(signal, 'ITIMER_REAL')
                and threading.current_thread() is threading.main_thread()
            )
            if not can_use_alarm:
                return func(self, *args, **kwargs)

            previous_handler = signal.getsignal(signal.SIGALRM)
            previous_delay, previous_interval = signal.getitimer(
                signal.ITIMER_REAL
            )
            effective_timeout = timeout
            if previous_delay > 0:
                effective_timeout = min(effective_timeout, previous_delay)

View on GitHub (pinned to 6ec464fabd)

Solutions

  1. Increase the timeout/recv_timeout value for the asset or task
  2. Verify network reachability of the target (ping/telnet to port 22, check gateway chains)
  3. Fix the command being executed so it cannot block (add timeouts, redirect stdin, run non-interactively)
  4. Tune the prompt regex so device output is matched promptly and recv doesn't spin

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

timeout = int(params.get('recv_timeout') or 0)
if timeout <= 0 or timeout < expected_command_duration:
    params['recv_timeout'] = max(60, expected_command_duration * 2)

Try / catch

for attempt in range(3):
    try:
        return client.run_command(cmd)
    except TimeoutError as e:
        if attempt == 2:
            module.fail_json(msg=f'Remote op failed after retries: {e}')
        time.sleep(2 ** attempt)

Prevention

When it happens

Trigger: A decorated remote-client method (connect, exec, send/recv, etc.) exceeding self.timeout seconds; a hung SSH TCP connect, a command that blocks forever, or a prompt regex that never matches the device output so recv loops until the alarm fires.

Common situations: Device/gateway unreachable or slow (firewall drop causing long SYN retries); recv_timeout set too low for slow network gear; a shell command waiting for stdin on a managed asset; network packet loss during large output transfer.

Understand the failure class

Related errors


AI-assisted analysis of jumpserver/jumpserver@6ec464fabd (2026-08-28). Data as JSON: /api/errors/0a2a26ffe0f9da72. Report an issue: GitHub.