{"record":{"id":"b0ff341f32145217","repo":"santifer/career-ops","slug":"agentic-jobs-parsed-0-jobs-from-the-api-the-res","errorCode":null,"errorMessage":"agentic-jobs: parsed 0 jobs from the API — the response shape likely changed","messagePattern":"agentic-jobs: parsed 0 jobs from the API — the response shape likely changed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/agentic-jobs.mjs","lineNumber":193,"sourceCode":"      // Trust the API's own reported page size over our constant, in case it\n      // ever differs from the documented default.\n      const effectivePageSize = typeof json.meta?.per_page === 'number' && json.meta.per_page > 0 ? json.meta.per_page : PAGE_SIZE;\n\n      for (const record of records) {\n        const job = normalizeAgenticJob(record);\n        if (job && !seen.has(job.url)) {\n          seen.add(job.url);\n          jobs.push(job);\n        }\n      }\n\n      if (jobs.length >= MAX_JOBS) break;\n      if (records.length < effectivePageSize) break; // short page — last one\n      if (total !== null && page * effectivePageSize >= total) break;\n    }\n\n    if (jobs.length === 0) {\n      throw new Error('agentic-jobs: parsed 0 jobs from the API — the response shape likely changed');\n    }\n    return jobs.slice(0, MAX_JOBS);\n  },\n};\n","sourceCodeStart":175,"sourceCodeEnd":198,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/agentic-jobs.mjs#L175-L198","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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.","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."],"exampleFix":"// before\nif (jobs.length === 0) throw new Error('agentic-jobs: parsed 0 jobs...');\n// after (diagnosable)\nif (jobs.length === 0) {\n  throw new Error(`agentic-jobs: parsed 0 jobs — sample record: ${JSON.stringify(records?.[0])?.slice(0, 300)}`);\n}","handlingStrategy":"validation","validationCode":"const json = await fetch('https://agentic-engineering-jobs.com/api/v1/jobs?page=1').then(r => r.json());\nif (Array.isArray(json.data) && json.data.length === 0 && json.meta?.total > 0) {\n  throw new Error('API reports total>0 but returned 0 records — parser/shape mismatch, do not run scan');\n}","typeGuard":"function looksParseable(record) {\n  return !!record && typeof record === 'object' &&\n    typeof record.title === 'string' && typeof record.slug === 'string';\n}","tryCatchPattern":"try {\n  jobs = await provider.fetch(entry, ctx);\n} catch (err) {\n  if (String(err.message).includes('parsed 0 jobs')) {\n    console.error('Board feed parsed empty — verify upstream schema via the OpenAPI spec before assuming the board is empty');\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["api","empty-result","schema-change","normalization"],"backgroundTag":"empty-result-set","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}