{"record":{"id":"7ad7e6e362abd3c1","repo":"santifer/career-ops","slug":"jobvite-cannot-derive-a-company-id-for-entry-na","errorCode":null,"errorMessage":"jobvite: cannot derive a company id for ${entry.name} — set company_eid: or an api: URL with ?c=","messagePattern":"jobvite: cannot derive a company id for (.+?) — set company_eid: or an api: URL with \\?c=","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/jobvite.mjs","lineNumber":294,"sourceCode":"/** @type {Provider} */\nexport default {\n  id: 'jobvite',\n\n  detect(entry) {\n    const eid = resolveConfiguredEid(entry);\n    if (eid) return { url: buildFeedUrl(eid) };\n    // A vanity URL alone still identifies this provider; the eId is resolved\n    // at fetch time via discovery.\n    const slug = resolveSlug(entry);\n    return slug ? { url: buildBoardUrl(slug) } : null;\n  },\n\n  async fetch(entry, ctx) {\n    let eid = resolveConfiguredEid(entry);\n\n    if (!eid) {\n      const slug = resolveSlug(entry);\n      if (!slug) throw new Error(`jobvite: cannot derive a company id for ${entry.name} — set company_eid: or an api: URL with ?c=`);\n      const boardUrl = buildBoardFetchUrl(slug);\n      assertJobviteHost(boardUrl);\n      // redirect:'error' here, not 'manual'. A board that still redirects once\n      // fr=true&nl=1 is present is a retired slug answering\n      // search.jobvite.com?invalid=1, and that must fail loudly.\n      const html = await fetchTextWithRetry(ctx, boardUrl, { redirect: 'error' }, RETRY_POLICY);\n      eid = extractEidFromBoard(html);\n      if (!eid) {\n        throw new Error(\n          `jobvite: could not find companyEId on ${boardUrl} for ${entry.name}. ` +\n          `Set it explicitly with company_eid: (find it in the board page source as companyEId: '…').`,\n        );\n      }\n    }\n\n    const feedUrl = buildFeedUrl(eid);\n    assertJobviteHost(feedUrl);\n    try {","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/jobvite.mjs#L276-L312","documentation":"Thrown during fetch() when the provider cannot resolve a Jobvite companyEId by any of its three resolution paths: no company_eid: field, no api: URL with a c= query param, and no resolvable vanity slug from the careers_url. The XML feed requires the opaque companyEId (e.g. 'q6NaVfwI') which does not appear in the careers URL — so an entry lacking all three identifiers cannot build a feed URL and must fail loudly rather than silently return zero jobs.","triggerScenarios":"A portals.yml job_boards entry marked provider: jobvite with a careers_url that is not a Jobvite vanity URL (extractSlug fails) and no company_eid or api field set; an entry where careers_url was deleted but company_eid was never added.","commonSituations":"Onboarding a new Jobvite tenant by copying an entry template and forgetting to fill in the identifier; an entry that relied on a careers_url which later changed shape so resolveSlug() no longer matches.","solutions":["Set company_eid: on the portal entry with the opaque ID (preferred — open the company's Jobvite board page, view source, find companyEId: '…').","Alternatively, set an api: URL of the form https://app.jobvite.com/...?c=<eId>.","Ensure careers_url is a valid Jobvite vanity URL (e.g. https://jobs.jobvite.com/<slug>) so the discovery path can resolve the eId at fetch time."],"exampleFix":"# before (portals.yml) — no identifier\nacme:\n  provider: jobvite\n  name: Acme\n\n# after — explicit eId\nacme:\n  provider: jobvite\n  name: Acme\n  company_eid: q6NaVfwI","handlingStrategy":"validation","validationCode":"function hasJobviteIdentifier(entry) {\n  return Boolean(entry.company_eid)\n    || (/\\?c=/.test(entry.api || ''))\n    || (/jobvite\\.com/i.test(entry.careers_url || ''));\n}\n// before scan:\nfor (const e of jobviteEntries) {\n  if (!hasJobviteIdentifier(e)) console.warn(`missing jobvite id: ${e.name}`);\n}","typeGuard":"/** @param {any} entry @returns {boolean} */\nfunction jobviteEntryIsComplete(entry) {\n  return Boolean(entry && (\n    entry.company_eid ||\n    (typeof entry.api === 'string' && /[?&]c=/.test(entry.api)) ||\n    (typeof entry.careers_url === 'string' && /jobvite\\.com/i.test(entry.careers_url))\n  ));\n}","tryCatchPattern":null,"preventionTips":["Always set company_eid: when adding a Jobvite entry — it is the most robust identifier and skips discovery.","Run a config audit that flags jobvite entries lacking all three identifier paths.","Document the eId discovery steps (view board page source, find companyEId) in your onboarding checklist."],"tags":["jobvite","config","company-eid","missing-identifier"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}