santifer/career-ops · error · Error

radancy: cannot resolve search-jobs URL for ${entry.name}

Error message

radancy: cannot resolve search-jobs URL for ${entry.name}

What it means

The radancy provider's fetch() throws when resolveListUrl(entry) returns null. resolveListUrl reads entry.api || entry.careers_url, parses it, requires an http: or https: protocol, and normalizes the path to a /<lang>/search-jobs endpoint. Because Radancy hosts branded career sites on arbitrary domains, detect() always returns null — the provider must be wired explicitly with provider: radancy plus a search-jobs api/careers_url.

Source

Thrown at providers/radancy.mjs:273

function resolveMaxJobs(entry) {
  const v = entry?.max_jobs;
  if (Number.isInteger(v) && v > 0) return v;
  return DEFAULT_MAX_JOBS;
}

/** @type {Provider} */
export default {
  id: 'radancy',

  detect() {
    // Branded hosts carry no stable Radancy token in the URL — wire explicitly
    // with `provider: radancy`. No auto-detection.
    return null;
  },

  async fetch(entry, ctx) {
    const listUrl = resolveListUrl(entry);
    if (!listUrl) throw new Error(`radancy: cannot resolve search-jobs URL for ${entry.name}`);
    const origin = new URL(listUrl).origin;

    const wait = (ms) => (ctx.sleep ? ctx.sleep(ms) : new Promise((r) => setTimeout(r, ms)));
    const maxPages = resolveMaxPages(entry);
    const maxJobs = resolveMaxJobs(entry);
    const jobs = [];
    const seen = new Set();
    // Proof of life across BOTH transports: any resolved request — including a
    // fragment 200 that parses to zero rows — proves the tenant is reachable,
    // so a later HTML page-1 failure must not read as "unreachable".
    let succeededOnce = false;

    // ── Preferred transport: the JSON results fragment ───────────────────────
    // Tried first because on legacy-markup tenants the ?p=N HTML page carries a
    // multi-megabyte facet blob per page (see the transport note up top). Any
    // failure here — non-JSON, no results, endpoint absent — falls through to
    // the HTML walk below, so tenants without this endpoint are unaffected.
    if (typeof ctx.fetchJson === 'function') {

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Add an api: or careers_url: to the entry pointing at the tenant's search-jobs page (e.g. https://careers.munichre.com/search-jobs or https://careers.acme.com/en/search-jobs).
  2. Confirm the entry is tagged provider: radancy — auto-detection is intentionally disabled for branded hosts.
  3. Verify the URL string is a well-formed absolute http(s) URL with no leading/trailing whitespace.
  4. Run detect(entry) before fetch; since detect always returns null for radancy, ensure you are dispatching by the explicit provider field instead.

Example fix

# before — portals.yml entry with provider but no URL
- name: Munich Re
  provider: radancy
# after
- name: Munich Re
  provider: radancy
  api: https://careers.munichre.com/search-jobs
Defensive patterns

Strategy: validation

Validate before calling

// radancy detect() always returns null — must dispatch by explicit provider field
function shouldRunRadancy(entry) {
  if (entry.provider !== 'radancy') return false;
  const raw = entry.api || entry.careers_url || '';
  try {
    const u = new URL(raw);
    return u.protocol === 'http:' || u.protocol === 'https:';
  } catch { return false; }
}
if (!shouldRunRadancy(entry)) {
  console.warn(`skip ${entry.name}: radancy needs provider:radancy + http(s) api/careers_url`);
}

Type guard

null

Try / catch

try {
  await provider.fetch(entry, ctx);
} catch (e) {
  if (/cannot resolve search-jobs URL/.test(e.message)) {
    console.warn(`[skip] ${entry.name}: add api/careers_url for radancy`);
  } else throw e;
}

Prevention

When it happens

Trigger: fetch() is called on an entry missing both api and careers_url; the URL is unparseable by new URL(); the protocol is neither http: nor https: (e.g. a mailto: or relative path); detect() was bypassed and fetch invoked directly on a non-Radancy entry.

Common situations: A portals.yml row sets provider: radancy but forgets the api: or careers_url: line; the entry was built from an API response that did not include a careers_url; the URL has a leading space or smart-quote characters from copy-paste.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/8f0c7e4b4ca6fb68. Report an issue: GitHub.