santifer/career-ops · error · Error

eightfold: cannot derive API URL for ${entry.name}

Error message

eightfold: cannot derive API URL for ${entry.name}

What it means

The primary eightfold misconfiguration error: resolveTenant(entry) returned null, meaning neither entry.api nor entry.careers_url is an https URL whose hostname matches /^[a-z0-9-]+\.eightfold\.ai$/i. Eightfold hosts branded career sites for enterprises, but the API is host-pinned to *.eightfold.ai, so a branded CNAME (careers.<company>.com) is deliberately NOT accepted — the entry must point at the canonical tenant host. An optional entry.domain overrides the ?domain= query param for multi-brand tenants.

Source

Thrown at providers/eightfold.mjs:277

  return Number.isFinite(hint) && hint > 0 ? Math.min(fromEntry, Math.floor(hint)) : fromEntry;
}

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

  detect(entry) {
    try {
      const tenant = resolveTenant(entry);
      return tenant ? { url: buildApiUrl(tenant, 0, PAGE_SIZE) } : null;
    } catch {
      return null;
    }
  },

  async fetch(entry, ctx) {
    const tenant = resolveTenant(entry);
    if (!tenant) throw new Error(`eightfold: cannot derive API URL for ${entry.name}`);

    const maxPages = resolveMaxPages(entry, ctx);
    const all = [];
    /** @type {number|null} */
    let total = null;

    for (let page = 0; page < maxPages; page++) {
      const start = page * PAGE_SIZE;
      const apiUrl = buildApiUrl(tenant, start, PAGE_SIZE);
      assertEightfoldUrl(apiUrl); // SSRF guard before every fetch
      if (page > 0) await sleep(INTER_PAGE_DELAY_MS, ctx);

      const json = /** @type {any} */ (await fetchJsonWithRetry(
        /** @type {any} */ (ctx),
        apiUrl,
        {
          // redirect:'error' prevents SSRF via a server-side redirect; with
          // assertEightfoldUrl above it guarantees the final hostname stays

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Set api: (or careers_url:) to the canonical eightfold.ai tenant URL, e.g. https://bayer.eightfold.ai/careers. For multi-brand tenants, add domain: <brand> to scope the board.
  2. If you only have the branded CNAME, resolve it to its eightfold.ai origin (the CNAME target) and configure that.
  3. Gate with provider.detect(entry) (returns null when resolveTenant does) before fetch().

Example fix

# before — branded CNAME, rejected
- name: Bayer
  provider: eightfold
  careers_url: https://careers.bayer.com

# after — canonical eightfold.ai tenant host
- name: Bayer
  provider: eightfold
  api: https://bayer.eightfold.ai/careers
Defensive patterns

Strategy: validation

Validate before calling

import eightfold from './providers/eightfold.mjs';
if (!eightfold.detect(entry)) {
  // neither api: nor careers_url is https://<tenant>.eightfold.ai — set api: to the canonical host
}

Type guard

/** True when entry resolves to an Eightfold tenant host. */
function isEightfoldEntry(entry) {
  for (const raw of [entry?.api, entry?.careers_url]) {
    if (typeof raw !== 'string' || !raw) continue;
    try {
      const p = new URL(raw);
      if (p.protocol === 'https:' && /^[a-z0-9-]+\.eightfold\.ai$/i.test(p.hostname)) return true;
    } catch { /* try next */ }
  }
  return false;
}

Try / catch

try { await eightfold.fetch(entry, ctx); }
catch (e) {
  if (/^eightfold: cannot derive API URL/.test(e.message)) {
    // config issue — set api: to https://<tenant>.eightfold.ai; do not retry
  } else throw e;
}

Prevention

When it happens

Trigger: entry.api/entry.careers_url is missing, unparseable, non-https, or its hostname is not <tenant>.eightfold.ai (e.g. the branded careers.<company>.com CNAME). resolveTenant checks both entry.api then entry.careers_url and returns null only if neither matches.

Common situations: Configuring the branded careers.bayer.com CNAME instead of bayer.eightfold.ai; using an http URL; omitting both api: and careers_url; a multi-brand tenant where the canonical host is correct but a typo breaks the regex.

Related errors


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