santifer/career-ops · error · Error
agentic-jobs: parsed 0 jobs from the API — the response shap
Error message
agentic-jobs: parsed 0 jobs from the API — the response shape likely changed
What it means
After paginating through all agentic-jobs pages (respecting the MAX_JOBS=2000 and MAX_PAGES=40 caps), if zero jobs were collected the provider throws. The reasoning: a genuinely empty board is implausible for this feed, so parsing 0 jobs almost certainly means the per-record normalizer (normalizeAgenticJob) no longer matches the record shape — every record got normalized to null and was skipped. This is a 'parsed nothing' sentinel that distinguishes 'feed empty' (shouldn't happen) from 'we silently lost every job to a shape change'.
Source
Thrown at providers/agentic-jobs.mjs:193
// Trust the API's own reported page size over our constant, in case it
// ever differs from the documented default.
const effectivePageSize = typeof json.meta?.per_page === 'number' && json.meta.per_page > 0 ? json.meta.per_page : PAGE_SIZE;
for (const record of records) {
const job = normalizeAgenticJob(record);
if (job && !seen.has(job.url)) {
seen.add(job.url);
jobs.push(job);
}
}
if (jobs.length >= MAX_JOBS) break;
if (records.length < effectivePageSize) break; // short page — last one
if (total !== null && page * effectivePageSize >= total) break;
}
if (jobs.length === 0) {
throw new Error('agentic-jobs: parsed 0 jobs from the API — the response shape likely changed');
}
return jobs.slice(0, MAX_JOBS);
},
};
View on GitHub (pinned to 9b17a8ac97)
Solutions
- Inspect normalizeAgenticJob in providers/agentic-jobs.mjs to see which fields it requires and how it returns null when they're missing.
- Reproduce with `curl '<API_BASE>/jobs?page=1'` and compare a real record's keys against the normalizer's expected fields.
- If the record layout changed (e.g. fields nested under attributes), update normalizeAgenticJob to read from the new shape.
- If a required field was renamed, update the field access in the normalizer.
- Run the provider's tests after the change.
Example fix
// Example: upstream wrapped job fields under `attributes` (JSON:API style)
// before
function normalizeAgenticJob(record) {
const url = record?.url;
const title = record?.title;
if (!url || !title) return null;
...
}
// after
function normalizeAgenticJob(record) {
const a = record?.attributes ?? record; // tolerate both shapes
const url = a?.url;
const title = a?.title;
if (!url || !title) return null;
...
} Defensive patterns
Strategy: validation
Validate before calling
// Sanity-check the normalizer against a sample record before a full sweep.
const sample = await ctx.fetchJson(`${API_BASE}/jobs?page=1`);
const first = sample?.data?.[0];
const normalized = normalizeAgenticJob(first);
if (!normalized) {
throw new Error('agentic-jobs normalizer rejects sample record — field shape likely changed; aborting sweep.');
Type guard
/** @param {unknown} j @returns {j is { url: string, title: string, company?: string, location?: string } | null} */
function isNormalizedJob(j) {
if (!j || typeof j !== 'object') return false;
const o = /** @type {any} */ (j);
return typeof o.url === 'string' && typeof o.title === 'string';
} Try / catch
try {
const jobs = await provider.fetch(entry, ctx);
} catch (err) {
if (/parsed 0 jobs/.test(String(err?.message))) {
console.error('agentic-jobs: normalizer rejected every record. curl the API, compare record keys to normalizeAgenticJob, update it.');
}
throw err;
} Prevention
- Keep normalizeAgenticJob defensive but explicit about required fields, and log (sample) a rejected record's keys when it returns null — silent null-loss is exactly what this guard exists to catch.
- Pin a fixture record in CI so a nesting change (e.g. JSON:API attributes) fails the test, not production.
- If the API moves fields under `attributes`, tolerate both shapes (`record?.attributes ?? record`) to ease migrations.
When it happens
Trigger: The API returned well-formed `{data:[...]}` pages (so error 138 did not fire), but normalizeAgenticJob returned null for every record — typically because each record is missing required fields the normalizer checks (url, title, etc.), or the record's field layout changed so the normalizer's destructuring yields garbage. The total reached 0 across all pages.
Common situations: Upstream added a nesting level (e.g. job fields moved under a `attributes` sub-object, common in JSON:API); the `url` or `title` field was renamed, so the normalizer's required-field guard rejects every record; a localized/censored response dropped fields the normalizer requires.
Related errors
- agentic-jobs: unexpected API response shape on page ${page}
- a16z-speedrun-talent: unexpected API response on page ${page
- agentic-jobs: invalid URL: ${url}
- USAGE
- Apify did not return a run id: ${JSON.stringify(body).slice(
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/b0ff341f32145217.
Report an issue: GitHub.