santifer/career-ops · error · Error
jibeapply: cannot derive API URL for ${entry.name}
Error message
jibeapply: cannot derive API URL for ${entry.name} What it means
Thrown by jibeapply fetch() when neither an explicit entry.api (validated by validateExplicitApi, which requires https) nor a derivable API URL from careers_url (toApiUrl requires https AND a hostname matching ^[a-z0-9-]+\.jibeapply\.com$) yields a usable endpoint. fetch() prefers entry.api so branded/iCIMS-hosted JibeApply sites work, then falls back to deriving from a jibeapply.com careers_url; both failing means no API endpoint is reachable.
Source
Thrown at providers/jibeapply.mjs:98
id: 'jibeapply',
detect(entry) {
const url = entry.careers_url;
if (typeof url !== 'string') return null;
const apiUrl = toApiUrl(url);
if (!apiUrl) return null;
return { url: apiUrl };
},
async fetch(entry, ctx) {
const url = entry.careers_url;
if (typeof url !== 'string' || !url) throw new Error('jibeapply: careers_url required');
// Prefer an explicit entry.api (allows iCIMS-hosted, branded JibeApply sites
// that share the same JSON schema but aren't on jibeapply.com).
const apiUrl = (typeof entry.api === 'string' && validateExplicitApi(entry.api))
|| toApiUrl(url);
if (!apiUrl) throw new Error(`jibeapply: cannot derive API URL for ${entry.name}`);
const first = await ctx.fetchJson(apiUrl, { redirect: 'error' });
const total = first.totalCount ?? 0;
// Use the actual number of items returned as page size — some implementations
// set `count` to the total rather than the per-page count.
const pageSize = first.jobs?.length || first.count || DEFAULT_PAGE_SIZE;
const allJobs = [...(first.jobs ?? [])];
if (total > pageSize && pageSize > 0) {
const maxPages = resolveMaxPages(entry);
const pages = Math.min(Math.ceil(total / pageSize), maxPages);
// Sequential, not concurrent (mirrors providers/4dayweek.mjs, thehub.mjs,
// arbeitnow.mjs, workday.mjs) — a single tenant's API has no reason to
// receive a burst of parallel requests, and a mid-run failure stops
// cleanly with whatever pages were already gathered instead of
// discarding them (Promise.all would fail the whole batch on one error).
for (let page = 2; page <= pages; page++) {
const u2 = new URL(apiUrl);
u2.searchParams.set('page', String(page));View on GitHub (pinned to 9b17a8ac97)
Solutions
- For branded (non-jibeapply.com) JibeApply sites, set both careers_url (any non-empty string, see error 210) AND api: to the https JSON endpoint (e.g. https://careers.acme.com/api/jobs).
- For standard tenants, ensure careers_url is the https://<slug>.jibeapply.com form so toApiUrl can derive /api/jobs.
- Confirm api: uses https: — validateExplicitApi rejects anything else.
- Verify with detect(): if provider.detect(entry) returns null and you have no valid entry.api, fetch() will throw this.
Example fix
# before (branded domain, no api) - name: Acme provider: jibeapply careers_url: https://careers.acme.com/jobs # after - name: Acme provider: jibeapply careers_url: https://careers.acme.com/jobs api: https://careers.acme.com/api/jobs
Defensive patterns
Strategy: validation
Validate before calling
// Mirror fetch()'s resolution: try explicit api (https), then derive from jibeapply.com.
function resolveJibeapplyApi(entry) {
if (typeof entry.api === 'string') {
try { const u = new URL(entry.api); if (u.protocol === 'https:') return u.href; } catch {}
}
if (typeof entry.careers_url === 'string') {
try {
const u = new URL(entry.careers_url);
if (u.protocol === 'https:' && /^[a-z0-9-]+\.jibeapply\.com$/i.test(u.hostname)) {
return new URL('/api' + u.pathname, u.origin).href;
}
} catch {}
}
return null;
} Type guard
/** True when a JibeApply API endpoint is derivable from the entry. */
function isJibeapplyDerivable(entry) {
return resolveJibeapplyApi(entry) !== null;
} Try / catch
try {
const jobs = await jibeapplyProvider.fetch(entry, ctx);
} catch (err) {
if (/cannot derive API URL/.test(err.message)) {
console.error(`config: ${entry.name} — ${err.message} (set api: https://... or a *.jibeapply.com careers_url)`);
} else {
throw err;
}
} Prevention
- For branded (non-jibeapply.com) JibeApply sites, always set BOTH careers_url and an https api:.
- Ensure entry.api uses https: — validateExplicitApi rejects anything else.
- For standard tenants, use the https://<slug>.jibeapply.com careers_url form.
When it happens
Trigger: careers_url is on a branded custom domain (not *.jibeapply.com) AND entry.api is missing, non-https, or malformed; entry.api is set to an http URL (validateExplicitApi rejects non-https); careers_url hostname has an invalid character for the jibeapply.com regex.
Common situations: An iCIMS-acquired JibeApply tenant running on a branded domain where someone set careers_url to the branded URL but forgot the matching api: field; setting api: to a plain-http internal endpoint; a typo in the careers_url host breaking the regex.
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/0317533d81d9e66b.
Report an issue: GitHub.