santifer/career-ops · error · Error

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

Error message

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

What it means

avature's `resolveConfig` returns null when neither `entry.api`/`entry.careers_url` (or whatever fields it inspects) yields an `avature.net` origin. `fetch` then throws, naming the entry. The provider can only operate against a `*.avature.net` tenant host.

Source

Thrown at providers/avature.mjs:140

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

  detect(entry) {
    const url = entry.api || entry.careers_url || '';
    if (typeof url !== 'string') return null;
    try {
      const host = new URL(url).host.toLowerCase();
      if (host === 'avature.net' || host.endsWith('.avature.net')) return { url };
    } catch {
      /* not absolute */
    }
    return null;
  },

  async fetch(entry, ctx) {
    const cfg = resolveConfig(entry);
    if (!cfg) throw new Error(`avature: cannot resolve origin for ${entry.name}`);
    const maxPages = Math.min(
      HARD_MAX_PAGES,
      Number.isFinite(entry.max_pages) && entry.max_pages > 0 ? Number(entry.max_pages) : DEFAULT_MAX_PAGES,
    );

    // Pagination key. An explicit `offset_param` pins it (and disables the
    // auto-switch below); otherwise start with `jobOffset` and self-heal. A
    // non-string/empty override falls back to the default so a malformed entry
    // can't produce `?=N`.
    const pinned = typeof entry.offset_param === 'string' && entry.offset_param.trim();
    let offsetParam = pinned ? entry.offset_param.trim() : 'jobOffset';
    let canHeal = !pinned; // once the key is pinned, never auto-switch

    const jobs = [];
    const seen = new Set();
    const sleep = (ms) => (typeof ctx?.sleep === 'function' ? ctx.sleep(ms) : new Promise((r) => setTimeout(r, ms)));

    const getPage = async (param, page) => {

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Set `careers_url` (or `api:`) to the full `https://<tenant>.avature.net` origin.
  2. Double-check the host really is an Avature tenant before assigning the provider.
  3. If the company uses a different ATS, switch the entry's `provider:` accordingly.

Example fix

# before
- name: Acme
  provider: avature
  careers_url: https://careers.acme.com/

# after
- name: Acme
  provider: avature
  careers_url: https://acme.avature.net/fp/jobs
Defensive patterns

Strategy: type-guard

Validate before calling

// Pre-check that the entry resolves to an avature origin
function looksLikeAvature(entry) {
  const u = entry.api || entry.careers_url;
  if (typeof u !== 'string') return false;
  try {
    const h = new URL(u).host.toLowerCase();
    return h === 'avature.net' || h.endsWith('.avature.net');
  } catch { return false; }
}
if (!looksLikeAvature(entry)) {
  console.warn(`avature: skipping ${entry.name} — no avature.net origin in api/careers_url`);
  continue;
}

Type guard

/** @param {any} e */
function hasAvatureOrigin(e) {
  const u = e?.api ?? e?.careers_url;
  if (typeof u !== 'string') return false;
  try {
    const h = new URL(u).host.toLowerCase();
    return h === 'avature.net' || h.endsWith('.avature.net');
  } catch { return false; }
}

Try / catch

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

Prevention

When it happens

Trigger: `resolveConfig(entry)` returns null — the entry has no URL whose host is `avature.net` or ends with `.avature.net`. The detect() `try`/`catch` shows non-absolute URLs are silently rejected, so a relative URL also yields null.

Common situations: An entry marked `provider: avature` points at a corporate careers page (Workday/Greenhouse/custom) rather than the avature tenant, or the careers_url is relative/missing.

Related errors


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