santifer/career-ops · error · Error

beesite: cannot resolve search host for ${entry.name}

Error message

beesite: cannot resolve search host for ${entry.name}

What it means

beesite's `resolveConfig` returns null when the entry provides no usable search host (no valid `api:`/`careers_url` that resolves to a beesite endpoint). `fetch` throws naming the entry rather than making a request to nowhere.

Source

Thrown at providers/beesite.mjs:146

function resolveMaxPages(entry) {
  const v = entry?.max_pages;
  if (Number.isInteger(v) && v > 0) return Math.min(v, MAX_PAGES);
  return MAX_PAGES;
}

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

  detect(entry) {
    const url = entry.api || entry.careers_url || '';
    if (typeof url !== 'string') return null;
    return resolveConfig({ api: url }) ? { url } : null;
  },

  async fetch(entry, ctx) {
    const cfg = resolveConfig(entry);
    if (!cfg) throw new Error(`beesite: cannot resolve search host for ${entry.name}`);

    const wait = (ms) => (ctx.sleep ? ctx.sleep(ms) : new Promise((r) => setTimeout(r, ms)));
    const maxPages = resolveMaxPages(entry);
    const jobs = [];
    const seen = new Set();
    let total = null;

    for (let page = 0; page < maxPages; page++) {
      if (page > 0) await wait(PAGE_DELAY_MS);
      const json = await ctx.fetchJson(buildSearchUrl(cfg, page * PAGE_SIZE + 1), {
        redirect: 'error',
        headers: { accept: 'application/json' },
      });
      const { total: pageTotal, rows } = parseSearchResult(json);
      if (total === null) total = pageTotal;
      if (rows.length === 0) break; // past the last page

      let fresh = 0;

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Provide a valid `api:` or `careers_url:` for the beesite search endpoint.
  2. Confirm the URL passes `resolveConfig` — use `detect()` to validate before calling `fetch`.
  3. If the company isn't on beesite, switch the entry's `provider:`.

Example fix

# before
- name: Acme
  provider: beesite

# after
- name: Acme
  provider: beesite
  api: https://acme.jobs.beesite.de/api/search
Defensive patterns

Strategy: type-guard

Validate before calling

// Use detect() to confirm the entry resolves before fetching
const detected = provider.detect(entry);
if (!detected) {
  console.warn(`beesite: skipping ${entry.name} — no search host resolvable (add api/careers_url)`);
  continue;
}

Type guard

/** @param {any} e */
function hasBeesiteConfig(e) {
  const u = e?.api || e?.careers_url;
  if (typeof u !== 'string' || !u) return false;
  // Mirror detect()'s test: resolveConfig must accept it
  try { return !!resolveConfig({ api: u }); } catch { return false; }
}

Try / catch

try {
  const cfg = resolveConfig(entry);
  if (!cfg) throw new Error(`beesite: cannot resolve search host for ${entry.name}`);
  // ...fetch
} catch (err) {
  if (/cannot resolve search host/.test(err.message)) { console.warn(err.message); return []; }
  throw err;
}

Prevention

When it happens

Trigger: `resolveConfig(entry)` returns null in `fetch`. `detect()` shows `resolveConfig({api: url})` is used to test validity — so a non-string, empty, or non-beesite URL yields null. Thrown before any network call.

Common situations: An entry marked `provider: beesite` has no `api:`/`careers_url`, points at a non-beesite host, or carries a relative/malformed URL that fails beesite's internal host check.

Related errors


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