{"record":{"id":"45c129b423ccc2b5","repo":"santifer/career-ops","slug":"retired-message","errorCode":null,"errorMessage":"RETIRED_MESSAGE","messagePattern":"RETIRED_MESSAGE","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"providers/echojobs.mjs","lineNumber":138,"sourceCode":"  // `posted_at` is already epoch milliseconds.\n  if (Number.isFinite(j.posted_at) && j.posted_at > 0) job.postedAt = j.posted_at;\n  return job;\n}\n\n/** @type {Provider} */\nexport default {\n  id: 'echojobs',\n\n  detect(entry) {\n    return entry?.provider === 'echojobs' ? { url: FEED_BASE } : null;\n  },\n\n  async fetch() {\n    // Deliberately no network call: the feed is confirmed gone (see the file\n    // header), and career-ops does not work around bot protection. Throwing\n    // immediately, with a message naming the cause, is what turns \"expected\n    // { jobs: [...] }\" into something a user can act on.\n    throw new Error(RETIRED_MESSAGE);\n  },\n};\n","sourceCodeStart":120,"sourceCodeEnd":141,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/echojobs.mjs#L120-L141","documentation":"The EchoJobs provider is permanently retired: the board-wide public feed at https://echojobs.io/api/jobs now answers with an HTTP 429 Vercel bot-protection checkpoint and the site's robots.txt disallows /api. Since career-ops does not work around bot protection, fetch() deliberately makes no network call and throws this explanatory message immediately. detect() is intentionally left matching `provider: echojobs` so stale configurations surface this clear message instead of a silent no-provider match.","triggerScenarios":"Any call to fetch() on the echojobs provider — i.e. a portals.yml entry still carrying `provider: echojobs`. The throw is unconditional; there is no input, network state, or configuration that avoids it.","commonSituations":"A portals.yml entry for EchoJobs left in place after the feed went dark (retired 2026-08-20, #2976); a scan run over an uncleaned config; a tutorial or template that still recommends echojobs as a provider.","solutions":["Remove the `provider: echojobs` entry from portals.yml — this is the intended and only resolution.","Consult docs/SUPPORTED_JOB_BOARDS.md for currently supported boards as a replacement source.","If you need those listings, use the underlying ATS providers directly (job URLs in the old feed pointed at the companies' own Greenhouse/Lever/Ashby boards).","Do not attempt to proxy or spoof the feed — the retirement is deliberate policy, not a fixable outage."],"exampleFix":"// before (portals.yml)\n- name: echojobs\n  provider: echojobs\n// after — entry removed entirely\n// (optionally replace with direct ATS entries, e.g. greenhouse/lever/ashby providers)","handlingStrategy":"validation","validationCode":"// guard before configuring or calling\nif (entry?.provider === 'echojobs') {\n  throw new Error('echojobs provider is retired (feed behind bot protection since 2026-08) — remove the entry from portals.yml');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await provider.fetch(entry, ctx);\n} catch (e) {\n  if (e.message.includes('echojobs: this feed is gone')) {\n    // expected retirement — remove the entry, no retry or fallback is meaningful\n    console.warn('Removing retired echojobs entry from scan rotation');\n  } else throw e;\n}","preventionTips":["Remove `provider: echojobs` from portals.yml immediately — the throw is unconditional.","Check docs/SUPPORTED_JOB_BOARDS.md before adding any provider to config.","Prefer direct ATS providers (greenhouse/lever/ashby) over third-party aggregate feeds, which rot faster.","Treat repeated retirement messages in scan logs as config debt to clean, not errors to suppress."],"tags":["deprecated","removed-provider","config","bot-protection"],"backgroundTag":"unsupported-operation","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}