{"record":{"id":"25f313deadfad365","repo":"santifer/career-ops","slug":"workday-cannot-derive-cxs-endpoint-for-entry-na","errorCode":null,"errorMessage":"workday: cannot derive CXS endpoint for ${entry.name}","messagePattern":"workday: cannot derive CXS endpoint for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/workday.mjs","lineNumber":565,"sourceCode":"\n  /**\n   * Fetch all job postings for a Workday-backed entry, paginating through\n   * the tenant's CXS API.\n   *\n   * Some tenants front their CXS API with Cloudflare bot management (seen\n   * live: geico) that 500s requests missing ordinary browser headers — the\n   * default UA/accept-language-less request trips it even over plain HTTPS\n   * with no other red flags. A real Chrome UA + accept-language + matching\n   * origin/referer clears it without needing per-tenant config (same fix\n   * as providers/glints.mjs's firewall).\n   *\n   * @param {{ name?: string, api?: string, careers_url?: string, max_pages?: number }} entry\n   * @param {{ fetchJson: (url: string, opts?: object) => Promise<any>, sinceMs?: number, maxPages?: number, syntheticEntries?: boolean }} ctx\n   * @returns {Promise<Array<{title: string, url: string, company: string, location: string, postedAt?: number}>>}\n   */\n  async fetch(entry, ctx) {\n    const ep = resolveEndpoint(entry);\n    if (!ep) throw new Error(`workday: cannot derive CXS endpoint for ${entry.name}`);\n\n    const postOpts = {\n      method: 'POST',\n      redirect: 'error',\n      headers: {\n        'content-type': 'application/json',\n        accept: 'application/json',\n        'user-agent': BROWSER_LIKE_USER_AGENT,\n        'accept-language': 'en-US,en;q=0.9',\n        origin: ep.origin,\n        referer: `${ep.jobBase}/`,\n      },\n    };\n    const makeBody = (offset, appliedFacets) => JSON.stringify({ limit: PAGE_SIZE, offset, searchText: '', appliedFacets });\n    const sinceMs = typeof ctx?.sinceMs === 'number' ? ctx.sinceMs : null;\n    const maxPages = resolveMaxPages(entry);\n\n    // Honor a context page cap — verify-portals' liveness probe sets","sourceCodeStart":547,"sourceCodeEnd":583,"githubUrl":"https://github.com/santifer/career-ops/blob/e7abd431fce9348a95261acac9e0c14779c35df8/providers/workday.mjs#L547-L583","documentation":"The Workday provider posts to a CXS (Candidate Experience Service) endpoint derived from the entry via resolveEndpoint. When the entry's api/careers_url cannot be resolved to a CXS endpoint, fetch throws before making any request.","triggerScenarios":"fetch(entry, ctx) with an entry lacking a resolvable Workday endpoint — no api field, a non-Workday careers_url, or a careers_url that does not match Workday CXS URL patterns.","commonSituations":"A portals.yml company entry where the careers page is Workday Classic (not CXS), a wrong tenant hostname, or a company that migrated off Workday.","solutions":["Provide the entry's api field with the full Workday CXS endpoint URL","Check the careers_url matches the Workday CXS pattern (…/wday/cxs/<tenant>/<site>/jobs) and fix it","Confirm the tenant/site names by loading the company's careers page; correct the entry config"],"exampleFix":"// before\n{ name: 'Acme', careers_url: 'https://acme.wd3.myworkdayjobs.com/careers' }\n// after\n{ name: 'Acme', api: 'https://acme.wd3.myworkdayjobs.com/wday/cxs/acme/careers/jobs' }","handlingStrategy":"validation","validationCode":"function hasWorkdayCxs(entry) {\n  const src = entry.api || entry.careers_url || '';\n  return /myworkdayjobs\\.com\\/wday\\/cxs\\/[\\w-]+\\/[\\w-]+/i.test(src) || /wday\\/cxs/.test(src);\n}","typeGuard":"const hasWorkdayCxs = (e) => /\\/wday\\/cxs\\/[\\w-]+\\/[\\w-]+/i.test(e.api || e.careers_url || '');","tryCatchPattern":"try { jobs = await workday.fetch(entry, ctx); } catch (e) { if (e.message.startsWith('workday: cannot derive CXS endpoint')) { console.warn(`${entry.name}: set entry.api to the full CXS /wday/cxs/<tenant>/<site>/jobs URL`); jobs = []; } else throw e; }","preventionTips":["Store the explicit CXS api URL (…/wday/cxs/tenant/site/jobs) instead of the careers page URL","Confirm tenant and site names from the live careers page when onboarding a company","Re-verify entries when a company migrates ATS versions"],"tags":["provider-config","workday","endpoint-resolution","cxs"],"backgroundTag":"missing-required-config-field","analyzedSha":"e7abd431fce9348a95261acac9e0c14779c35df8","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}