santifer/career-ops · error · Error

successfactors: cannot resolve origin for

Error message

successfactors: cannot resolve origin for ${entry.name}

What it means

The successfactors provider must resolve each entry to a concrete tenant origin/config via resolveConfig(entry). When the entry's URL matches no known SuccessFactors pattern and no explicit origin is configured, it throws with the entry's name. This is a fail-fast for entries the provider genuinely cannot talk to.

Solutions

  1. Set an explicit origin/sfVariant (e.g. sfVariant: csb) in the entry so resolveConfig succeeds
  2. Point careers_url at the actual SuccessFactors tenant URL (careers.xx.successfactors.eu or *.jobs2web.com)
  3. Confirm the company still uses SuccessFactors; if it moved to another ATS, switch the entry's provider
  4. Check resolveConfig's accepted patterns in providers/successfactors.mjs and align the URL

Example fix

// before
- name: Acme
  provider: successfactors
  careers_url: 'https://acme.com/careers'
// after
- name: Acme
  provider: successfactors
  careers_url: 'https://acme.successfactors.eu/careers'
  # or: sfVariant: csb
Defensive patterns

Strategy: validation

Validate before calling

const SF_RE = /(successfactors\.(eu|com)|jobs2web\.com)/i;
if (String(entry.provider) === 'successfactors' && !(entry.careers_url && SF_RE.test(entry.careers_url))) {
  throw new Error(`${entry.name}: successfactors needs a careers_url on a successfactors.eu/com or jobs2web.com host (or explicit sfVariant/origin)`);
}

Type guard

null

Try / catch

try {
  offers = await provider.fetch(entry, ctx);
} catch (e) {
  if (e.message.startsWith('successfactors: cannot resolve origin')) {
    console.warn(`${entry.name}: provider cannot map URL to an SF tenant — fix entry config`);
    return [];
  }
  throw e;
}

Prevention

When it happens

Trigger: A portals.yml entry has provider: successfactors but its careers_url matches neither successfactors.eu/com nor jobs2web.com patterns, or lacks the URL fields resolveConfig expects; entry.sfVariant/origin hints are missing for a tenant needing them.

Common situations: A company migrated off SuccessFactors so the URL no longer matches; someone pointed the successfactors provider at a generic careers page; a custom vanity domain not covered by the regexes was configured without explicit config.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/56f40d550a5a8a04. Report an issue: GitHub.

Appendix: source

Thrown at providers/successfactors.mjs:417

    startrow += tiles.length;
  }
  // The cap is checked between pages, so the last page can overshoot it.
  return jobs.slice(0, MAX_JOBS);
}

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

  detect(entry) {
    const url = entry.api || entry.careers_url || '';
    if (/successfactors\.(eu|com)|jobs2web\.com/i.test(url)) return { url };
    return null;
  },

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

    // Explicit opt-in goes straight to CSB. RMK tenants (the majority) run the
    // tile scraper; only when it comes back empty — the CSB empty-shell
    // signature — do we auto-fall back to the JSON API, so an unflagged CSB
    // tenant still works and a genuinely-empty RMK board costs one extra probe.
    if (String(entry.sfVariant || '').toLowerCase() === 'csb') {
      return fetchCsb(entry, cfg, ctx);
    }
    const rmkJobs = await fetchRmk(entry, cfg, ctx);
    if (rmkJobs.length > 0) return rmkJobs;
    // RMK answered (healthy, possibly legitimately empty) — the CSB call here
    // is only a probe for the empty-shell signature, so it must not turn a
    // failing/absent CSB endpoint into a dead-board throw.
    return fetchCsb(entry, cfg, ctx, { probe: true });
  },
};

View on GitHub (pinned to aac998c7ed)