{"record":{"id":"c8e0d6cc3c1b3edf","repo":"santifer/career-ops","slug":"jobbankca-all-keywords-length-keyword-request","errorCode":null,"errorMessage":"jobbankca: all ${keywords.length} keyword request(s) failed — ${errors[0]}","messagePattern":"jobbankca: all (.+?) keyword request\\(s\\) failed — (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/jobbankca.mjs","lineNumber":298,"sourceCode":"          }\n          break;\n        }\n\n        const rawEntryCount = (String(xml ?? '').match(/<entry\\b[^>]*>[\\s\\S]*?<\\/entry>/gi) || []).length;\n        const parsed = parseJobBankFeed(xml);\n        for (const job of parsed) {\n          if (!byUrl.has(job.url)) byUrl.set(job.url, job);\n        }\n        if (rawEntryCount < PAGE_SIZE) break; // short feed page — end of this keyword's results\n      }\n      if (!keywordFailed) succeeded++;\n    }\n\n    // Total outage = every keyword's first request failed. A keyword that\n    // answered with zero results is not an outage — recall-first, same as\n    // arbeitsagentur.mjs.\n    if (succeeded === 0 && errors.length) {\n      throw new Error(`jobbankca: all ${keywords.length} keyword request(s) failed — ${errors[0]}`);\n    }\n\n    return [...byUrl.values()];\n  },\n};\n","sourceCodeStart":280,"sourceCodeEnd":304,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/providers/jobbankca.mjs#L280-L304","documentation":"fetch() fans out one request per keyword and tolerates individual failures, but if every keyword's first request failed (succeeded === 0) it declares a total outage and throws, surfacing the first underlying error. A keyword returning zero results is NOT an outage — only network/HTTP failures count.","triggerScenarios":"All keyword requests to the Job Bank endpoint fail: network down, DNS failure, TLS error, 429 rate-limit on the first page of each keyword, 5xx from the service, or a proxy blocking outbound HTTPS.","commonSituations":"Corporate proxy/firewall blocking jobbank.canada.ca, transient Job Bank outage or maintenance window, aggressive scanning triggering rate limits, running in an offline CI container.","solutions":["Read errors[0] in the message — it contains the actual root cause (ECONNREFUSED, 403, 429, etc.) and fix that first","Retry later with backoff if it's a 429/5xx transient outage","Verify network/DNS/proxy access: curl -v https://jobbank.canada.ca/... from the same machine","Reduce request rate / add delays between keyword requests if rate-limited"],"exampleFix":"// before: no retry\nawait jobbankca.fetch(entry, ctx);\n// after\ntry {\n  await jobbankca.fetch(entry, ctx);\n} catch (e) {\n  if (/429|timeout|ECONN/i.test(e.message)) {\n    await new Promise(r => setTimeout(r, 30_000));\n    await jobbankca.fetch(entry, ctx);\n  } else throw e;\n}","handlingStrategy":"retry","validationCode":"// Preflight reachability check before a full scan\nconst probe = await fetch('https://jobbank.canada.ca', { method: 'HEAD' }).catch(() => null);\nif (!probe || !probe.ok) console.warn('jobbank.ca unreachable — scan may fail');","typeGuard":null,"tryCatchPattern":"try {\n  const jobs = await jobbankca.fetch(entry, ctx);\n} catch (e) {\n  const m = e.message.match(/all (\\d+) keyword request\\(s\\) failed — (.*)/);\n  if (m) {\n    console.error(`jobbankca outage, root cause: ${m[2]}`);\n    if (/429|5\\d\\d|timeout|ECONN|ENOTFOUND/i.test(m[2])) scheduleRetry(60_000);\n  } else throw e;\n}","preventionTips":["Read the errors[0] tail of the message — it names the real root cause","Back off on 429/5xx; add per-keyword delays to stay under rate limits","Verify outbound access to jobbank.canada.ca from CI/proxies with curl before blaming the library","Treat zero-results-per-keyword as success — only full request failure is an outage"],"tags":["network","outage","rate-limit","jobbankca"],"backgroundTag":"all-requests-failed","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}