{"record":{"id":"7634df7bf942ea8d","repo":"santifer/career-ops","slug":"getonbrd-invalid-category-json-stringify-c","errorCode":null,"errorMessage":"getonbrd: invalid category ${JSON.stringify(c)} — expected a slug like \"programming\" or \"machine-learning-ai\"","messagePattern":"getonbrd: invalid category (.+?) — expected a slug like \"programming\" or \"machine-learning-ai\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/getonbrd.mjs","lineNumber":57,"sourceCode":"/**\n * Resolve the categories to scan, in config order, deduped.\n *\n * `categories:` (array) wins over `category:` (string); neither → the\n * `programming` default, which keeps pre-existing entries byte-identical.\n * Exported for tests.\n *\n * @param {any} entry\n * @returns {string[]}\n */\nexport function resolveCategories(entry) {\n  const raw = entry?.categories !== undefined ? entry.categories : entry?.category;\n  if (raw === undefined || raw === null) return [DEFAULT_CATEGORY];\n\n  const list = Array.isArray(raw) ? raw : [raw];\n  const out = [];\n  for (const c of list) {\n    if (typeof c !== 'string' || !CATEGORY_SLUG_RE.test(c.trim())) {\n      throw new Error(\n        `getonbrd: invalid category ${JSON.stringify(c)} — expected a slug like \"programming\" or \"machine-learning-ai\"`,\n      );\n    }\n    const slug = c.trim();\n    if (!out.includes(slug)) out.push(slug);\n  }\n  if (!out.length) {\n    throw new Error('getonbrd: `categories` is empty — omit it to use the \"programming\" default');\n  }\n  if (out.length > MAX_CATEGORIES) {\n    throw new Error(\n      `getonbrd: ${out.length} categories configured — cap is ${MAX_CATEGORIES} (each one costs up to max_pages requests)`,\n    );\n  }\n  return out;\n}\n\n/** @param {string} url */","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/providers/getonbrd.mjs#L39-L75","documentation":"getonbrd's resolveCategories validates each configured category against CATEGORY_SLUG_RE (lowercase kebab-case slugs). Non-string values or strings that are not valid slugs are rejected with an example of the expected format, preventing malformed API requests.","triggerScenarios":"categories configured as 'Machine Learning', 'programming,design' (comma-joined single string), '/programming', 42, null inside the array, or an empty-string element.","commonSituations":"Copy-pasting human-readable category names from the getonbrd website instead of their URL slugs; YAML config quirks producing numbers or nested lists; trailing slashes from copying URLs.","solutions":["Replace each category value with its URL slug, e.g. 'programming', 'machine-learning-ai'","Lowercase and hyphenate multi-word categories ('Machine Learning' → 'machine-learning-ai')","Ensure categories is a list of plain strings, not one comma-joined string","Trim stray whitespace/slashes from each entry"],"exampleFix":"// before\ncategories: ['Machine Learning', '/programming']\n// after\ncategories: ['machine-learning-ai', 'programming']","handlingStrategy":"validation","validationCode":"const CATEGORY_SLUG_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;\nconst cats = (cfg.categories ?? []).map(c => typeof c === 'string' ? c.trim() : c);\nconst bad = cats.filter(c => typeof c !== 'string' || !CATEGORY_SLUG_RE.test(c));\nif (bad.length) throw new Error('Invalid getonbrd category slugs: ' + JSON.stringify(bad));","typeGuard":"function isValidCategorySlug(c) {\n  return typeof c === 'string' && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(c.trim());\n}","tryCatchPattern":"try {\n  const jobs = await getonbrdProvider.fetch(entry, ctx);\n} catch (e) {\n  if (String(e.message).startsWith('getonbrd: invalid category')) {\n    console.error('Fix categories for', entry.name, '— use URL slugs like \"programming\"');\n    return [];\n  }\n  throw e;\n}","preventionTips":["Copy slugs from getonbrd category URLs, never display names","Normalize (lowercase, hyphenate, trim) categories when writing config","Lint portals.yml category entries against the slug regex in CI"],"tags":["validation","configuration","slug"],"backgroundTag":"invalid-slug-format","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}