{"record":{"id":"82c14f44c1cb88be","repo":"ruvnet/RuView","slug":"unsupported-host-name","errorCode":null,"errorMessage":"Unsupported host: ${name}","messagePattern":"Unsupported host: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"harness/homecore/src/hosts/index.js","lineNumber":15,"sourceCode":"// SPDX-License-Identifier: MIT\n\nimport claudeCode from './claude-code.js';\nimport codex from './codex.js';\n\nexport { claudeCode, codex };\n\nexport const HOSTS = Object.freeze({\n  'claude-code': claudeCode,\n  codex,\n});\n\nexport function getHost(name) {\n  const host = HOSTS[name];\n  if (!host) throw new Error(`Unsupported host: ${name}`);\n  return host;\n}\n","sourceCodeStart":1,"sourceCodeEnd":18,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/harness/homecore/src/hosts/index.js#L1-L18","documentation":"RateLimitMiddleware.dispatch (rate_limit.py:335) raises HTTPException 429 'Rate limit exceeded' when the per-client sliding-window counter denies the request. The response carries X-RateLimit-Limit/Remaining/Reset headers plus a computed Retry-After (seconds until window reset). Limiting keys derive from the client identity (IP or authenticated user), with a default_limit and a higher authenticated_limit.","triggerScenarios":"Bursting more than default_limit requests from one IP within window_size seconds while unauthenticated; a poll loop or k6/locust load test hammering /api/* endpoints; many users behind one NAT/IP sharing a single unauthenticated bucket; retries without backoff after 429s.","commonSituations":"Load tests against a default-configured server; aggressive frontend polling; CI suites running parallel requests from one runner IP; health checks counted against the same bucket when the path is not in the skip list.","solutions":["Honor the Retry-After header: sleep that many seconds, then resume with exponential backoff","Authenticate requests so the higher authenticated_limit applies instead of the anonymous per-IP limit","Reduce request rate (client-side throttle/caching) or batch endpoints","Server-side: raise default_limit/authenticated_limit in Settings or set enable_rate_limiting=False for local development; add hot paths to the skip list"],"exampleFix":"# before\nfor i in range(1000):\n    requests.get(url, headers=headers)  # triggers 429\n# after\nresp = requests.get(url, headers=headers)\nif resp.status_code == 429:\n    time.sleep(int(resp.headers[\"Retry-After\"]) + 1)\n    resp = requests.get(url, headers=headers)","handlingStrategy":"retry","validationCode":"def should_throttle(response) -> bool:\n    \"\"\"Detect the 429 this middleware raises before planning the next call.\"\"\"\n    return response.status_code == 429 or \"X-RateLimit-Remaining\" in response.headers and response.headers[\"X-RateLimit-Remaining\"] == \"0\"","typeGuard":null,"tryCatchPattern":"import time\nfrom fastapi import HTTPException\n\ntry:\n    response = client.get(\"/api/data\", headers=headers)\nexcept HTTPException as e:\n    if getattr(e, \"status_code\", None) == 429:\n        wait = int(e.headers[\"Retry-After\"]) + 1 if e.headers else 1\n        time.sleep(wait)\n        response = client.get(\"/api/data\", headers=headers)  # single retry after backoff\n    else:\n        raise","preventionTips":["Read X-RateLimit-Remaining and back off before it hits 0","Authenticate to move to the higher authenticated_limit bucket","Add jittered exponential backoff to all API clients","Exclude health-check paths from rate limiting server-side"],"tags":["rate-limiting","http-429","middleware","fastapi"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}