santifer/career-ops · error · Error

getonbrd: invalid category ${JSON.stringify(c)} — expected a

Error message

getonbrd: invalid category ${JSON.stringify(c)} — expected a slug like "programming" or "machine-learning-ai"

What it means

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.

Source

Thrown at providers/getonbrd.mjs:57

/**
 * Resolve the categories to scan, in config order, deduped.
 *
 * `categories:` (array) wins over `category:` (string); neither → the
 * `programming` default, which keeps pre-existing entries byte-identical.
 * Exported for tests.
 *
 * @param {any} entry
 * @returns {string[]}
 */
export function resolveCategories(entry) {
  const raw = entry?.categories !== undefined ? entry.categories : entry?.category;
  if (raw === undefined || raw === null) return [DEFAULT_CATEGORY];

  const list = Array.isArray(raw) ? raw : [raw];
  const out = [];
  for (const c of list) {
    if (typeof c !== 'string' || !CATEGORY_SLUG_RE.test(c.trim())) {
      throw new Error(
        `getonbrd: invalid category ${JSON.stringify(c)} — expected a slug like "programming" or "machine-learning-ai"`,
      );
    }
    const slug = c.trim();
    if (!out.includes(slug)) out.push(slug);
  }
  if (!out.length) {
    throw new Error('getonbrd: `categories` is empty — omit it to use the "programming" default');
  }
  if (out.length > MAX_CATEGORIES) {
    throw new Error(
      `getonbrd: ${out.length} categories configured — cap is ${MAX_CATEGORIES} (each one costs up to max_pages requests)`,
    );
  }
  return out;
}

/** @param {string} url */

View on GitHub (pinned to 1696bec4d0)

Solutions

  1. Replace each category value with its URL slug, e.g. 'programming', 'machine-learning-ai'
  2. Lowercase and hyphenate multi-word categories ('Machine Learning' → 'machine-learning-ai')
  3. Ensure categories is a list of plain strings, not one comma-joined string
  4. Trim stray whitespace/slashes from each entry

Example fix

// before
categories: ['Machine Learning', '/programming']
// after
categories: ['machine-learning-ai', 'programming']
Defensive patterns

Strategy: validation

Validate before calling

const CATEGORY_SLUG_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
const cats = (cfg.categories ?? []).map(c => typeof c === 'string' ? c.trim() : c);
const bad = cats.filter(c => typeof c !== 'string' || !CATEGORY_SLUG_RE.test(c));
if (bad.length) throw new Error('Invalid getonbrd category slugs: ' + JSON.stringify(bad));

Type guard

function isValidCategorySlug(c) {
  return typeof c === 'string' && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(c.trim());
}

Try / catch

try {
  const jobs = await getonbrdProvider.fetch(entry, ctx);
} catch (e) {
  if (String(e.message).startsWith('getonbrd: invalid category')) {
    console.error('Fix categories for', entry.name, '— use URL slugs like "programming"');
    return [];
  }
  throw e;
}

Prevention

When it happens

Trigger: categories configured as 'Machine Learning', 'programming,design' (comma-joined single string), '/programming', 42, null inside the array, or an empty-string element.

Common situations: 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.

Related errors


AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01). Data as JSON: /api/errors/7634df7bf942ea8d. Report an issue: GitHub.