santifer/career-ops · error · Error
agentic-jobs: parsed 0 jobs from the API — the response…
Error message
agentic-jobs: parsed 0 jobs from the API — the response shape likely changed
What it means
After the paging loop, the provider requires at least one parsed job; zero jobs from a board-wide feed means the response shape no longer matches the parser (records are fetched but none normalize), not that the board is empty. It throws so scan results don't silently report an empty provider as healthy.
Solutions
- Fetch a page manually (curl 'https://agentic-engineering-jobs.com/api/v1/jobs?page=1') and diff the record fields against what normalizeAgenticJob/the parser expects; update field mappings.
- Check the OpenAPI spec for a schema/version change and bump the provider to the current response contract.
- Add a debug log of the first raw record when jobs.length===0 to see exactly what shape arrives.
- Confirm meta.total: if total>0 but zero records normalize, it's a parser mismatch; if the board genuinely emptied, treat it as upstream data loss, not a code bug.
Example fix
// before
if (jobs.length === 0) throw new Error('agentic-jobs: parsed 0 jobs...');
// after (diagnosable)
if (jobs.length === 0) {
throw new Error(`agentic-jobs: parsed 0 jobs — sample record: ${JSON.stringify(records?.[0])?.slice(0, 300)}`);
} Defensive patterns
Strategy: validation
Validate before calling
const json = await fetch('https://agentic-engineering-jobs.com/api/v1/jobs?page=1').then(r => r.json());
if (Array.isArray(json.data) && json.data.length === 0 && json.meta?.total > 0) {
throw new Error('API reports total>0 but returned 0 records — parser/shape mismatch, do not run scan');
} Type guard
function looksParseable(record) {
return !!record && typeof record === 'object' &&
typeof record.title === 'string' && typeof record.slug === 'string';
} Try / catch
try {
jobs = await provider.fetch(entry, ctx);
} catch (err) {
if (String(err.message).includes('parsed 0 jobs')) {
console.error('Board feed parsed empty — verify upstream schema via the OpenAPI spec before assuming the board is empty');
}
throw err;
} Prevention
- Diff a live record against the normalizer's expected fields after any upstream API announcement.
- Keep the 0-jobs check in place — never downgrade it to a warning; an empty aggregator feed is almost always a shape change.
- When editing the normalizer, test against a captured real payload, not hand-made fixtures.
When it happens
Trigger: The API returned pages successfully but every record failed normalization (field renames like companyName -> company_name, changed slug/title structure), or json.data was consistently an empty array while meta.total claimed >0 — i.e. every parsed record was dropped before reaching `jobs`.
Common situations: Upstream API renamed the fields the normalizer reads; a filter/normalizer regression after a provider edit; the API started wrapping records in an extra nesting level ({ data: { items: [...] } }) while per-page length checks still passed; site pivoted to a new API version at /api/v2 leaving v1 serving stub payloads.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- agentic-jobs: unexpected API response shape on page
- No free models found in API response
- 4dayweek: unexpected API response on page
- a16z-speedrun-talent: unexpected API response on page
- All active models failed. Last error
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/b0ff341f32145217.
Report an issue: GitHub.
Appendix: 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 aac998c7ed)