{"record":{"id":"cade3c5985fa0533","repo":"santifer/career-ops","slug":"tkms-cannot-resolve-jobs-host-for-entry-name","errorCode":null,"errorMessage":"tkms: cannot resolve jobs host for ${entry.name}","messagePattern":"tkms: cannot resolve jobs host for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/tkms.mjs","lineNumber":137,"sourceCode":"function resolveMaxPages(entry) {\n  const v = entry?.max_pages;\n  if (Number.isInteger(v) && v > 0) return Math.min(v, MAX_PAGES);\n  return MAX_PAGES;\n}\n\n/** @type {Provider} */\nexport default {\n  id: 'tkms',\n\n  detect(entry) {\n    const url = entry.api || entry.careers_url || '';\n    if (typeof url !== 'string') return null;\n    return resolveConfig({ api: url }) ? { url } : null;\n  },\n\n  async fetch(entry, ctx) {\n    const cfg = resolveConfig(entry);\n    if (!cfg) throw new Error(`tkms: cannot resolve jobs host for ${entry.name}`);\n\n    const wait = (ms) => (ctx.sleep ? ctx.sleep(ms) : new Promise((r) => setTimeout(r, ms)));\n    const maxPages = resolveMaxPages(entry);\n    const jobs = [];\n    const seen = new Set();\n\n    for (let page = 0; page < maxPages; page++) {\n      if (page > 0) await wait(PAGE_DELAY_MS);\n      const json = await ctx.fetchJson(cfg.queryApi, {\n        method: 'POST',\n        redirect: 'error',\n        headers: { 'content-type': 'application/json', accept: 'application/json' },\n        body: JSON.stringify({ searchQuery: '', filter: {}, subclient: cfg.subclient, locale: cfg.locale, page }),\n      });\n      const { nextPage, rows } = parseQuery(json, cfg);\n      if (rows.length === 0) break;\n\n      let fresh = 0;","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/tkms.mjs#L119-L155","documentation":"resolveConfig requires a valid https URL whose host is exactly 'jobs.tkmsgroup.com'; anything else (unparseable, non-https, or a different host) returns null and fetch throws. TKMS is a single-employer provider hardcoded to that one careers host, so the entry must point at it. An optional tkms: block can override subclient/locale but cannot change the host.","triggerScenarios":"entry.api/careers_url is missing, malformed, non-https, or points at a host other than jobs.tkmsgroup.com. A provider: tkms override on an entry with a different URL also hits this.","commonSituations":"The entry was added with the wrong corporate domain (e.g. tkms.com) rather than the careers app host, or the URL line was omitted.","solutions":["Set careers_url (or api) to https://jobs.tkmsgroup.com","Ensure the scheme is https and the host is exactly jobs.tkmsgroup.com","Optionally add a tkms: block with subclient/locale overrides if needed (defaults: subclient 'tkms', locale 'en')","If the company is not thyssenkrupp Marine Systems, this provider does not apply"],"exampleFix":"# before\n- name: TKMS\n  provider: tkms\n  careers_url: https://www.tkms.com\n# after\n- name: TKMS\n  provider: tkms\n  careers_url: https://jobs.tkmsgroup.com","handlingStrategy":"validation","validationCode":"// Pre-check the TKMS host before fetch.\nimport { resolveConfig } from './providers/tkms.mjs';\nif (!resolveConfig(entry)) {\n  console.warn(`${entry.name}: tkms requires careers_url https://jobs.tkmsgroup.com`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pin tkms entries to https://jobs.tkmsgroup.com.","Run resolveConfig(entry) in a config-lint pass before scanning.","Remember tkms is single-employer; do not point it at other domains."],"tags":["config","tkms","url-validation","hostname","portals-yml","detection"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}