jumpserver/jumpserver · error · ValueError

Invalid SSH prompt regular expression

Error message

Invalid SSH prompt regular expression

What it means

Raised in the remote SSH client's __init__ when re.compile of the configured prompt pattern fails with re.error or TypeError — i.e. the 'prompt' module parameter is not a valid Python regular expression (compiled with re.DOTALL|re.IGNORECASE). The client relies on this regex to detect device prompts, so an invalid one is fatal at construction.

Source

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

        self.module = module
        self.gateway_server = None
        self.client = paramiko.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.debug_enabled = _env_flag_enabled('JMS_REMOTE_CLIENT_DEBUG')
        self._debug_started_at = time.monotonic()
        self._debug_sequence = 0
        self._channel = None
        self._extra_secrets = set()

        self.buffer_size = 1024
        self.prompt = self.module.params['prompt']
        try:
            self._prompt_re = re.compile(
                self.prompt,
                re.DOTALL | re.IGNORECASE,
            )
        except (re.error, TypeError) as error:
            raise ValueError('Invalid SSH prompt regular expression') from error
        self.timeout = int(self.module.params.get('recv_timeout') or 0)
        self.delay_time = int(self.module.params.get('delay_time') or 0)
        if self.timeout <= 0:
            raise ValueError('recv_timeout must be greater than zero')
        if self.delay_time < 0:
            raise ValueError('delay_time cannot be negative')
        if self.delay_time >= self.timeout:
            raise ValueError('delay_time must be less than recv_timeout')
        self._last_command_sent_at = None
        self._decoder = codecs.getincrementaldecoder('utf-8')('replace')
        self._debug(
            'client.init',
            login_host=self.module.params.get('login_host'),
            login_port=self.module.params.get('login_port'),
            login_user=self.module.params.get('login_user'),
            become=self.module.params.get('become'),
            become_method=self.module.params.get('become_method'),
            become_user=self.module.params.get('become_user'),

View on GitHub (pinned to 6ec464fabd)

Solutions

  1. Test the prompt with Python: `import re; re.compile(p, re.DOTALL|re.IGNORECASE)`
  2. Fix the pattern: close brackets, use valid Python regex syntax, escape special chars meant literally
  3. Prefer simpler anchored patterns like r'[>#]\s*$' for common network prompts

Example fix

# before
prompt = r'[root@.*]#'  # unbalanced/invalid character class nesting

# after
prompt = r'[#$>]\s*$'
Defensive patterns

Strategy: validation

Validate before calling

import re
try:
    re.compile(prompt, re.DOTALL | re.IGNORECASE)
except (re.error, TypeError):
    raise ValueError(f'Invalid prompt regex: {prompt!r}')

Type guard

def is_valid_prompt_regex(p) -> bool:
    try:
        re.compile(p, re.DOTALL | re.IGNORECASE)
        return True
    except (re.error, TypeError):
        return False

Try / catch

try:
    client = RemoteClient(module)
except ValueError as e:
    if 'prompt regular expression' in str(e):
        module.fail_json(msg=f'Fix the asset prompt pattern: {e}')

Prevention

When it happens

Trigger: Passing a malformed prompt regex like '[unclosed', 'a{2,1}', or backslash sequences invalid in Python regex; passing None or a non-string that makes compile raise TypeError (though a missing value usually has a default).

Common situations: Customizing asset prompt patterns for network devices with regex syntax valid elsewhere (POSIX/PCRE edge cases) but not Python re; escaping bugs when templating prompts; overly greedy/wrongly-bracketed patterns pasted from device docs.

Related errors


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