santifer/career-ops · error · Error
icims: cannot derive portal origin for ${entry.name}
Error message
icims: cannot derive portal origin for ${entry.name} What it means
Thrown by icims fetch() when resolveOrigin(entry) returns null. resolveOrigin walks [entry.api, entry.careers_url] and accepts only entries that are https URLs whose hostname ends in .icims.com, returning the origin. Anything else — wrong host, http scheme, non-URL, or both fields absent — returns null, and detect() returns null silently while fetch() throws.
Source
Thrown at providers/icims.mjs:114
location: location ? decodeEntities(location[1].replace(/\s+/g, ' ').trim()) : '',
// no postedAt — iCIMS list pages have no date; see enrichDate.
});
}
return jobs;
}
/** @type {Provider} */
export default {
id: 'icims',
detect(entry) {
const origin = resolveOrigin(entry);
return origin ? { url: searchUrl(origin, 0) } : null;
},
async fetch(entry, ctx) {
const origin = resolveOrigin(entry);
if (!origin) throw new Error(`icims: cannot derive portal origin for ${entry.name}`);
const all = [];
let prevFirstUrl = null;
// Distinguishes "walked the whole board" from "stopped at the page cap".
// Exhausting the cap silently would drop every later posting and look
// identical to a complete board — the same failure mode the Workday
// truncation tag exists to prevent.
let reachedEnd = false;
for (let pageNum = 0; pageNum < ICIMS_MAX_PAGES; pageNum++) {
if (pageNum > 0) await sleep(INTER_PAGE_DELAY_MS, ctx);
const html = await ctx.fetchText(searchUrl(origin, pageNum), { headers: HEADERS, redirect: 'error' });
const pageJobs = parseIcimsSearchPage(html, origin, entry.name);
if (pageJobs.length === 0) { reachedEnd = true; break; } // past the last page
// Some tenants serve the last real page again for an out-of-range pr
// instead of an empty one — a repeated first URL means we're looping.
if (pageJobs[0].url === prevFirstUrl) { reachedEnd = true; break; }
prevFirstUrl = pageJobs[0].url;
all.push(...pageJobs);
}View on GitHub (pinned to 9b17a8ac97)
Solutions
- Set careers_url to the canonical https://careers-{tenant}.icims.com/jobs/search?ss=1 form (or any https *.icims.com URL).
- If the tenant uses a branded domain that is genuinely iCIMS-hosted but not on icims.com, that host is intentionally unsupported by auto-detect — confirm the icims.com backend URL and set api/careers_url to it.
- Validate with detect(): provider.detect(entry) returning null means fetch() will throw this too.
Example fix
# before - name: Acme provider: icims careers_url: https://careers.acme.com/jobs # after - name: Acme provider: icims careers_url: https://careers-acme.icims.com/jobs/search?ss=1
Defensive patterns
Strategy: validation
Validate before calling
const hit = icimsProvider.detect(entry);
if (!hit) {
console.warn(`icims: ${entry.name} — api/careers_url must be an https *.icims.com URL`);
continue;
}
const jobs = await icimsProvider.fetch(entry, ctx); Type guard
/** True when the entry can resolve an iCIMS portal origin. */
function isIcimsDerivable(entry) {
for (const raw of [entry?.api, entry?.careers_url]) {
if (typeof raw !== 'string' || !raw) continue;
try {
const u = new URL(raw);
if (u.protocol === 'https:' && u.hostname.endsWith('.icims.com')) return true;
} catch { /* ignore */ }
}
return false;
} Try / catch
try {
const jobs = await icimsProvider.fetch(entry, ctx);
} catch (err) {
if (/cannot derive portal origin/.test(err.message)) {
console.error(`config: ${entry.name} — ${err.message}`);
} else {
throw err;
}
} Prevention
- Use the canonical https://careers-{tenant}.icims.com form for careers_url.
- Branded (non-icims.com) domains are intentionally not auto-detected — find the icims.com backend URL.
- Gate entries through detect() so misconfigured boards are reported, not silently empty.
When it happens
Trigger: An entry tagged provider: icims whose careers_url/api is on a non-icims.com host (the company's branded domain that does not proxy iCIMS); an http:// URL (resolveOrigin requires https); a missing or non-string careers_url and no api; pasting a generic job-board URL against the icims provider.
Common situations: Some iCIMS tenants brand the portal onto their own domain (e.g. careers.acme.com) which still proxies icims.com on the backend but the hostname no longer ends in .icims.com; copy-pasting an http link; YAML misindentation leaving careers_url unset.
Related errors
- breezy: cannot derive API URL for ${entry.name}
- comeet: cannot derive API URL for ${entry.name} (set api: to
- consider: ${entry.name} needs an https careers_url on a publ
- csod: cannot resolve careersite URL for ${entry.name}
- deutschebahn: cannot resolve db.jobs search id for ${entry.n
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/6eb2798e1245084d.
Report an issue: GitHub.