{"record":{"id":"fef876581c7ab69b","repo":"santifer/career-ops","slug":"wttj-the-wttj-board-is-global-configure-explici","errorCode":null,"errorMessage":"wttj: the WTTJ board is global — configure explicit searches via `wttj: { queries: [\"…\"] }`","messagePattern":"wttj: the WTTJ board is global — configure explicit searches via `wttj: (.+?)`","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/wttj.mjs","lineNumber":144,"sourceCode":"      : 0;\n  if (min || max) {\n    job.salary = {\n      min: min || max,\n      max: max || min,\n      currency: typeof h.salary_currency === 'string' ? h.salary_currency.trim().toUpperCase() : '',\n    };\n  }\n  return job;\n}\n\n/** Resolve config: required queries list + optional per-query hit cap. */\nfunction resolveConfig(entry) {\n  const cfg = entry?.wttj && typeof entry.wttj === 'object' ? entry.wttj : {};\n  const queries = Array.isArray(cfg.queries)\n    ? cfg.queries.filter((q) => typeof q === 'string' && q.trim()).map((q) => q.trim())\n    : [];\n  if (queries.length === 0) {\n    throw new Error(\n      'wttj: the WTTJ board is global — configure explicit searches via `wttj: { queries: [\"…\"] }`',\n    );\n  }\n  const maxHits =\n    Number.isInteger(cfg.max_hits) && cfg.max_hits > 0 ? Math.min(cfg.max_hits, MAX_HITS_CAP) : DEFAULT_MAX_HITS;\n  return { queries, maxHits };\n}\n\n/** @type {Provider} */\nexport default {\n  id: 'wttj',\n\n  detect(entry) {\n    return entry?.provider === 'wttj' ? { url: SITE_ORIGIN } : null;\n  },\n\n  async fetch(entry, ctx) {\n    const { queries, maxHits } = resolveConfig(entry);","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/wttj.mjs#L126-L162","documentation":"WTTJ's board is global and huge, so the provider refuses to scan an arbitrary default slice — it requires an explicit wttj: { queries: [...] } block. resolveConfig throws when, after filtering, there are zero non-empty string queries.","triggerScenarios":"An entry with provider: wttj but no wttj: block; a wttj: block whose queries is missing / not an array / all-empty / contains non-strings; a typo like query: instead of queries:; queries placed at the entry root instead of under wttj:.","commonSituations":"User copies the WTTJ sample and deletes the queries; misspells queries; indents queries wrong so it lands outside the wttj: map.","solutions":["Add wttj: { queries: [\"finops\", \"data platform engineer\"] } to the entry.","Confirm the YAML indentation puts queries under wttj:, not at the entry root.","Optionally add max_hits (per-query, capped at 200) alongside queries."],"exampleFix":"# before\n- name: Welcome to the Jungle\n  provider: wttj\n# after\n- name: Welcome to the Jungle\n  provider: wttj\n  wttj:\n    queries: [\"finops\", \"data platform engineer\", \"snowflake\"]\n    max_hits: 100","handlingStrategy":"validation","validationCode":"function wttjQueriesConfigured(entry) {\n  const cfg = entry?.wttj && typeof entry.wttj === \"object\" ? entry.wttj : {};\n  return Array.isArray(cfg.queries) &&\n    cfg.queries.some(q => typeof q === \"string\" && q.trim());\n}\nif (entry.provider === \"wttj\" && !wttjQueriesConfigured(entry)) {\n  console.warn(`skip ${entry.name}: add wttj.queries`);\n  continue;\n}","typeGuard":"const hasWttjQueries = (e) => Array.isArray(e?.wttj?.queries) &&\n  e.wttj.queries.some(q => typeof q === \"string\" && q.trim());","tryCatchPattern":null,"preventionTips":["Always pair provider: wttj with a wttj.queries block.","Lint portals.yml for wttj entries lacking queries.","Watch for the query/queries singular typo."],"tags":["config","wttj","validation","portals-yml"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}