santifer/career-ops · error · Error
hecklerkoch: cannot resolve vacancy list for ${entry.name}
Error message
hecklerkoch: cannot resolve vacancy list for ${entry.name} What it means
Thrown by hecklerkoch fetch() when resolveListUrl(entry) returns null. resolveListUrl accepts only http(s) URLs whose host is exactly heckler-koch.com or a *.heckler-koch.com subdomain, and returns null for any other host, a non-URL string, or a non-http(s) scheme. detect() returns null silently for the same condition; fetch() turns it into a hard error.
Source
Thrown at providers/hecklerkoch.mjs:86
seen.add(id);
out.push({ id, title, url });
}
return out;
}
/** @type {Provider} */
export default {
id: 'hecklerkoch',
detect(entry) {
const url = entry.api || entry.careers_url || '';
if (typeof url !== 'string') return null;
return resolveListUrl({ api: url }) ? { url } : null;
},
async fetch(entry, ctx) {
const listUrl = resolveListUrl(entry);
if (!listUrl) throw new Error(`hecklerkoch: cannot resolve vacancy list for ${entry.name}`);
const html = await ctx.fetchText(listUrl, { headers: { accept: 'text/html' } });
const rows = parseListing(html);
const jobs = [];
for (const row of rows) {
jobs.push({ title: row.title, url: row.url, company: entry.name, location: '' });
if (jobs.length >= MAX_JOBS) break;
}
return jobs;
},
};
View on GitHub (pinned to 9b17a8ac97)
Solutions
- Set careers_url (or api) to https://heckler-koch.com/de/Karriere/Stellenangebote or any https://*.heckler-koch.com URL.
- If the entry is not actually Heckler & Koch, remove provider: hecklerkoch and let detect() route it to the right provider.
- Confirm with detect(): if provider.detect(entry) returns null, fetch() will throw this too.
Example fix
# before - name: Heckler & Koch provider: hecklerkoch careers_url: https://www.indeed.com/jobs?q=hk # after - name: Heckler & Koch provider: hecklerkoch careers_url: https://heckler-koch.com/de/Karriere/Stellenangebote
Defensive patterns
Strategy: validation
Validate before calling
const hit = hecklerkochProvider.detect(entry);
if (!hit) {
console.warn(`hecklerkoch: ${entry.name} — careers_url must be on heckler-koch.com or a subdomain`);
continue;
}
const jobs = await hecklerkochProvider.fetch(entry, ctx); Type guard
/** True when the entry can resolve an H&K vacancy list URL. */
function isHecklerkochDerivable(entry) {
const raw = entry?.api || entry?.careers_url;
if (typeof raw !== 'string') return false;
try {
const u = new URL(raw);
const host = u.host.toLowerCase();
return (u.protocol === 'https:' || u.protocol === 'http:')
&& (host === 'heckler-koch.com' || host.endsWith('.heckler-koch.com'));
} catch { return false; }
} Try / catch
try {
const jobs = await hecklerkochProvider.fetch(entry, ctx);
} catch (err) {
if (/cannot resolve vacancy list/.test(err.message)) {
console.error(`config: ${entry.name} — ${err.message}`);
} else {
throw err;
}
} Prevention
- Only point the hecklerkoch provider at heckler-koch.com / *.heckler-koch.com URLs.
- Use detect() as the entry gate — it mirrors resolveListUrl's accept criteria exactly.
- Do not tag non-H&K companies with provider: hecklerkoch.
When it happens
Trigger: An entry tagged provider: hecklerkoch whose api/careers_url points at a different host (e.g. the karriere.heckler-koch.com apply backend, which is a subdomain but the path may not be a Stellenangebote page — note resolveListUrl still accepts the subdomain and rewrites the path, so this is fine; the real trigger is a wholly different host); a careers_url that is not a string; a URL with an unsupported scheme like ftp.
Common situations: Wiring the apply-backend URL (karriere.heckler-koch.com) as careers_url expecting it to list jobs — it won't, but resolveListUrl still rewrites it to the Stellenangebote path so this should pass; pasting a third-party recruiter link; setting provider: hecklerkoch on a generic company that is not H&K.
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/64f136911629919c.
Report an issue: GitHub.