{"record":{"id":"05953eaa84dfac41","repo":"jackwener/OpenCLI","slug":"lobsters-domain-returned-http-resp-status","errorCode":null,"errorMessage":"lobsters domain returned HTTP ${resp.status}","messagePattern":"lobsters domain returned HTTP (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/lobsters/domain.js","lineNumber":66,"sourceCode":"    func: async (args) => {\n        const domain = requireDomain(args.domain);\n        const limit = requireBoundedInt(args.limit, 20, 25);\n        const url = `https://lobste.rs/domains/${encodeURIComponent(domain)}.json`;\n        let resp;\n        try {\n            resp = await fetch(url, { headers: { 'user-agent': 'opencli-lobsters-adapter (+https://github.com/jackwener/opencli)' } });\n        }\n        catch (err) {\n            throw new CommandExecutionError(\n                `lobsters domain request failed: ${err?.message ?? err}`,\n                'Check that lobste.rs is reachable from this network.',\n            );\n        }\n        if (resp.status === 404) {\n            throw new EmptyResultError('lobsters domain', `No Lobste.rs stories found for domain \"${domain}\".`);\n        }\n        if (!resp.ok) {\n            throw new CommandExecutionError(`lobsters domain returned HTTP ${resp.status}`);\n        }\n        let body;\n        try {\n            body = await resp.json();\n        }\n        catch (err) {\n            throw new CommandExecutionError(`lobsters domain returned malformed JSON: ${err?.message ?? err}`);\n        }\n        const list = Array.isArray(body) ? body : [];\n        if (!list.length) {\n            throw new EmptyResultError('lobsters domain', `No Lobste.rs stories found for domain \"${domain}\".`);\n        }\n        return list.slice(0, limit).map((item, i) => ({\n            rank: i + 1,\n            id: String(item.short_id ?? ''),\n            title: String(item.title ?? ''),\n            score: item.score != null ? Number(item.score) : null,\n            author: String(item.submitter_user ?? ''),","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/lobsters/domain.js#L48-L84","documentation":"This CommandExecutionError is thrown when the lobste.rs domain endpoint returns any non-success HTTP status other than 404 (which is handled separately as an empty result). It signals the request reached lobste.rs but the server rejected or failed it. The message embeds the raw status code so the developer can tell rate limiting (429), auth/permission (403), or server-side errors (5xx) apart.","triggerScenarios":"GET https://lobste.rs/domain/<domain>.json returns status 403, 429, 500, 502, 503, etc. — anything where resp.ok is false and resp.status !== 404.","commonSituations":"Hitting lobste.rs rate limits after scripted polling (HTTP 429), Cloudflare or proxy blocking the request (403), lobste.rs maintenance or partial outages (502/503), or a corporate proxy injecting error pages with 4xx/5xx codes.","solutions":["Read the HTTP status in the message and check lobste.rs availability/status page if it is 5xx.","If 429, back off and retry later; add caching or reduce polling frequency of the lobste.rs API.","If 403, retry from a different network/IP or check whether a proxy/firewall is blocking lobste.rs.","Wrap the call with an exponential-backoff retry for transient 5xx statuses."],"exampleFix":"// before\nconst stories = await cli.lobsters.domain('example.com'); // throws on 503\n\n// after\nasync function withRetry(fn, attempts = 3) {\n  for (let i = 0; i < attempts; i++) {\n    try { return await fn(); }\n    catch (e) {\n      if (i === attempts - 1 || !/HTTP 5\\d\\d/.test(String(e.message))) throw e;\n      await new Promise(r => setTimeout(r, 2 ** i * 500));\n    }\n  }\n}\nconst stories = await withRetry(() => cli.lobsters.domain('example.com'));","handlingStrategy":"retry","validationCode":"async function lobstersReachable() {\n  try {\n    const r = await fetch('https://lobste.rs/', { method: 'HEAD' });\n    return r.status < 500;\n  } catch {\n    return false;\n  }\n}\nif (!(await lobstersReachable())) {\n  console.error('lobste.rs is unreachable or returning server errors; aborting.');\n  return;\n}","typeGuard":"null","tryCatchPattern":"try {\n  const stories = await cli.lobsters.domain(domain);\n} catch (err) {\n  const m = /HTTP (\\d{3})/.exec(String(err.message));\n  if (m) {\n    const status = Number(m[1]);\n    if (status === 429) console.error('Rate limited by lobste.rs — wait before retrying.');\n    else if (status >= 500) console.error('lobste.rs server error — retry with backoff.');\n    else console.error(`lobste.rs rejected the request (HTTP ${status}).`);\n    return;\n  }\n  throw err;\n}","preventionTips":["Cache lobste.rs responses instead of polling on every invocation.","Implement exponential backoff for 429 and 5xx statuses.","Monitor lobste.rs status/outages before scripted bulk runs.","Set a reasonable User-Agent so proxies/CDNs do not reject your requests."],"tags":["network","http-error","rate-limit","cli"],"backgroundTag":"http-429-rate-limited","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}