santifer/career-ops · error · Error
lever: cannot derive API URL for ${entry.name}
Error message
lever: cannot derive API URL for ${entry.name} What it means
In fetch(), resolveApiUrl returns null/empty when it cannot produce an API URL — i.e. entry has neither an explicit api: field nor a careers_url it can derive a Lever slug from. Because detect() already swallows resolveApiUrl's exceptions and returns null, reaching fetch() with no URL means the entry was selected despite yielding no API endpoint.
Source
Thrown at providers/lever.mjs:61
return `https://api.${host[1]}/v0/postings/${slug}`;
}
/** @type {Provider} */
export default {
id: 'lever',
detect(entry) {
try {
const apiUrl = resolveApiUrl(entry);
return apiUrl ? { url: apiUrl } : null;
} catch {
return null;
}
},
async fetch(entry, ctx) {
const apiUrl = resolveApiUrl(entry);
if (!apiUrl) throw new Error(`lever: cannot derive API URL for ${entry.name}`);
assertLeverUrl(apiUrl);
const json = await ctx.fetchJson(apiUrl, { redirect: 'error' });
if (!Array.isArray(json)) return [];
return json.map(j => ({
title: j.text || '',
url: j.hostedUrl || '',
company: entry.name,
location: j.categories?.location || '',
// Lever's v0 postings list ships the full description for free (same
// payload, no per-job request) — enables scan.mjs content_filter.
description: typeof j.descriptionPlain === 'string' ? j.descriptionPlain : '',
postedAt: typeof j.createdAt === 'number' ? j.createdAt : undefined,
}));
},
};
View on GitHub (pinned to 9b17a8ac97)
Solutions
- Add an explicit api: https://api.lever.co/v0/postings/<slug> to the entry in portals.yml.
- Or set careers_url: https://jobs.lever.co/<slug> so the slug can be auto-derived.
- Confirm the entry should actually use provider: lever (it may belong to greenhouse/ashby).
- Ensure the orchestrator only calls fetch() on entries for which detect() returned non-null.
Example fix
# before (portals.yml) - name: Acme provider: lever careers_url: https://www.acme.com/careers # after - name: Acme provider: lever api: https://api.lever.co/v0/postings/acme careers_url: https://www.acme.com/careers
Defensive patterns
Strategy: validation
Validate before calling
// Verify detect() yields an API URL before calling fetch().
// Provider.detect() returns { url } or null — never call fetch on a null detect.
const detected = provider.detect(entry);
if (!detected || !detected.url) {
throw new Error(`config: lever entry ${entry.name} has no api URL (set api: or a lever.co careers_url)`);
} Type guard
/** @param {import('./providers/_types.js').Provider} provider @param {any} entry */
function canFetchLever(provider, entry) {
return Boolean(provider.detect?.(entry)?.url);
} Try / catch
try {
const detected = provider.detect(entry);
if (!detected?.url) throw new Error(`lever: cannot derive API URL for ${entry.name}`);
const jobs = await provider.fetch(entry, ctx);
} catch (err) {
console.warn(`skipping ${entry.name}: ${err.message}`);
} Prevention
- Every provider: lever entry should carry either an explicit api: URL or a careers_url on jobs.(eu.)?lever.co.
- Gate fetch() behind a truthy detect() in the orchestrator.
- Validate the lever entry config at load time so missing URLs fail fast with a clear message.
When it happens
Trigger: An entry reaches fetch() (the orchestrator called it directly, or detect returned a truthy {url} that later became empty) but entry.api is unset AND entry.careers_url does not match the jobs.(eu.)?lever.co/<slug> pattern. entry.name is interpolated so you know which portal entry is at fault.
Common situations: A portals.yml entry has provider: lever but neither api: nor a lever.co careers_url; the careers_url host pattern changed; detect() and fetch() were called out of order; the entry name has trailing characters that broke slug extraction.
Related errors
- gem: cannot derive board id for ${entry.name}
- getro: ${entry.name} needs a numeric 'getro_collection' in p
- justjoin: careers_url or api must be a trusted justjoin.it U
- lever: invalid URL: ${url}
- local-parser: parser.command is required
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/138c9463cd637090.
Report an issue: GitHub.