{"record":{"id":"8f0c7e4b4ca6fb68","repo":"santifer/career-ops","slug":"radancy-cannot-resolve-search-jobs-url-for-entr","errorCode":null,"errorMessage":"radancy: cannot resolve search-jobs URL for ${entry.name}","messagePattern":"radancy: cannot resolve search-jobs URL for (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/radancy.mjs","lineNumber":312,"sourceCode":"export function resolveMaxJobs(entry) {\n  const v = entry?.max_jobs;\n  if (Number.isInteger(v) && v > 0) return Math.min(v, MAX_JOBS_CAP);\n  return DEFAULT_MAX_JOBS;\n}\n\n/** @type {Provider} */\nexport default {\n  id: 'radancy',\n\n  detect() {\n    // Branded hosts carry no stable Radancy token in the URL — wire explicitly\n    // with `provider: radancy`. No auto-detection.\n    return null;\n  },\n\n  async fetch(entry, ctx) {\n    const listUrl = resolveListUrl(entry);\n    if (!listUrl) throw new Error(`radancy: cannot resolve search-jobs URL for ${entry.name}`);\n    const origin = new URL(listUrl).origin;\n\n    const wait = (ms) => (ctx.sleep ? ctx.sleep(ms) : new Promise((r) => setTimeout(r, ms)));\n    const maxPages = resolveMaxPages(entry);\n    const maxJobs = resolveMaxJobs(entry);\n    // ctx.maxPages is set only by verify-portals.mjs's bounded liveness probe\n    // (never during a real scan). While probing: cap the walk to that budget\n    // (SHOULD — reference providers/workday.mjs) so a healthy large board\n    // doesn't burn the probe's whole request allotment on one tenant, and\n    // propagate any ctx.fetch* rejection unwrapped instead of absorbing it\n    // into the normal partial-result handling (MUST). verify-portals\n    // identifies its own budget-exhaustion sentinel, ProbePageBudgetReached,\n    // by `instanceof`, and reads it as \"endpoint live, count unknown\"; a\n    // per-page catch that swallows it into a normal stopReason/break instead\n    // misreports a healthy board as broken. Reference: providers/vdab.mjs.\n    const probing = Number.isInteger(ctx?.maxPages) && ctx.maxPages > 0;\n    const effectiveMaxPages = probing ? Math.min(maxPages, ctx.maxPages) : maxPages;\n    const jobs = [];","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/radancy.mjs#L294-L330","documentation":"The radancy provider requires an explicitly configured Radancy search-jobs URL (it deliberately performs no auto-detection). resolveListUrl() returned null — no valid search-jobs URL could be derived from the entry — so fetch() aborts instead of guessing.","triggerScenarios":"fetch() invoked for an entry with no careers_url/search URL configured, or a URL that does not resolve to a Radancy search-jobs endpoint per the provider's resolver rules.","commonSituations":"An entry tagged `provider: radancy` in portals.yml lacks the careers_url field; the configured URL points at a company landing page rather than the Radancy jobs search path; a typo prevents URL parsing.","solutions":["Add or correct the careers_url so it points at the Radancy search-jobs page (e.g. https://<tenant>.<region>/search-jobs)","Confirm the entry declares provider: radancy and that its URL is a genuine Radancy-hosted board","Parse-test the URL (new URL(raw) must succeed and use https:)","If the company is not on Radancy, remove the provider override or switch to the correct provider"],"exampleFix":"// before (portals.yml)\n- name: Acme\n  provider: radancy\n// after\n- name: Acme\n  provider: radancy\n  careers_url: https://acme.aon.help/search-jobs","handlingStrategy":"validation","validationCode":"function hasRadancySearchUrl(entry) {\n  const raw = typeof entry.careers_url === 'string' ? entry.careers_url : '';\n  if (!raw) return false;\n  try { const u = new URL(raw); return u.protocol === 'https:' && /search-jobs|jobs|search/i.test(u.pathname); }\n  catch { return false; }\n}","typeGuard":"function isRadancyEntry(entry) {\n  return entry?.provider === 'radancy' && typeof entry?.careers_url === 'string' && entry.careers_url.length > 0;\n}","tryCatchPattern":"try {\n  await radancy.fetch(entry, ctx);\n} catch (err) {\n  if (err.message.includes('cannot resolve search-jobs URL')) {\n    console.warn(`Radancy entry ${entry.name} missing a valid search-jobs careers_url — skipping`);\n    return [];\n  }\n  throw err;\n}","preventionTips":["Radancy has no auto-detection: always pair provider: radancy with an explicit careers_url","Point careers_url at the /search-jobs path, not the company homepage","Validate the full portals.yml with a pre-flight check before running scans"],"tags":["config","url-validation","ats"],"backgroundTag":"invalid-url","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"}