{"record":{"id":"043ffddda0e9948a","repo":"odysseus-dev/odysseus","slug":"invalid-ssh-port","errorCode":null,"errorMessage":"Invalid ssh_port","messagePattern":"Invalid ssh_port","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"routes/_validators.py","lineNumber":27,"sourceCode":"_SSH_PORT_RE = re.compile(r\"^\\d{1,5}$\")\n\n\ndef validate_remote_host(v: str | None) -> str | None:\n    if v is None or v == \"\":\n        return None\n    if not _REMOTE_HOST_RE.match(v):\n        raise HTTPException(\n            400,\n            \"Invalid remote_host — must be host or user@host, no SSH option syntax\",\n        )\n    return v\n\n\ndef validate_ssh_port(v: str | None) -> str | None:\n    if v is None or v == \"\":\n        return None\n    if not _SSH_PORT_RE.fullmatch(str(v)):\n        raise HTTPException(400, \"Invalid ssh_port\")\n    port = int(v)\n    if port < 1 or port > 65535:\n        raise HTTPException(400, \"Invalid ssh_port\")\n    return str(port)\n","sourceCodeStart":9,"sourceCodeEnd":32,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/_validators.py#L9-L32","documentation":"HTTPException(400) from validate_ssh_port: the value does not fullmatch ^\\d{1,5}$ — it contains non-digit characters (letters, whitespace, a 'tcp://' prefix) or is empty after being passed as a non-string. This is the format-level guard before the numeric range check.","triggerScenarios":"Submitting ssh_port='22 ' (trailing space), 'port 22', '22/tcp', or a float like 22.0 in the request payload.","commonSituations":"Copy-pasting port from documentation prose; UI not trimming whitespace; serializing the field as a number with a decimal point on the client.","solutions":["Send the port as a plain digit string or integer, e.g. '22' or 2222","Trim whitespace client-side before submitting","Use the same field name the endpoint expects (ssh_port), not an alias"],"exampleFix":"# before\nssh_port=\"22/tcp\"\n# after\nssh_port=\"22\"","handlingStrategy":"validation","validationCode":"ssh_port = str(ssh_port or '').strip()\nif not ssh_port.isdigit():\n    raise ValueError('ssh_port must be digits only')","typeGuard":"def is_digits(v) -> bool:\n    s = str(v or '').strip()\n    return bool(s) and s.isdigit()","tryCatchPattern":"try:\n    resp = client.post('/api/remote', data={'ssh_port': p})\nexcept HTTPError as e:\n    if e.response.status_code == 400 and 'ssh_port' in e.response.text:\n        p = re.sub(r'\\D', '', str(p)); retry()\n    raise","preventionTips":["Trim whitespace client-side","Send numeric ports, never prose like '22/tcp'","Use typed number inputs in forms"],"tags":["http","validation","ssh","fastapi"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}