santifer/career-ops · error · Error

getonbrd: ${out.length} categories configured — cap is ${MAX

Error message

getonbrd: ${out.length} categories configured — cap is ${MAX_CATEGORIES} (each one costs up to max_pages requests)

What it means

resolveCategories enforces MAX_CATEGORIES because every configured category costs up to max_pages API requests per scan. Configuring more categories than the cap is rejected to protect rate limits and scan runtime.

Source

Thrown at providers/getonbrd.mjs:68

  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 */
function assertGetonbrdUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error(`getonbrd: invalid URL: ${url}`);
  }
  if (parsed.protocol !== 'https:') throw new Error(`getonbrd: URL must use HTTPS: ${url}`);
  if (parsed.hostname !== TRUSTED_HOST) {
    throw new Error(`getonbrd: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_HOST}`);
  }

View on GitHub (pinned to 1696bec4d0)

Solutions

  1. Trim the list to the MAX_CATEGORIES most relevant slugs (the cap value is in the message)
  2. Split the workload across multiple portal entries or scheduled runs
  3. Increase MAX_CATEGORIES in the provider only if you accept the extra request cost per category

Example fix

// before
categories: ['programming', 'design', 'data-science', 'devops', 'product', 'marketing', 'sales', 'finance']
// after (cap-aware)
categories: ['programming', 'data-science', 'devops']
Defensive patterns

Strategy: validation

Validate before calling

const MAX = 3; // mirror provider MAX_CATEGORIES
if ((entry.categories ?? []).length > MAX) {
  entry.categories = entry.categories.slice(0, MAX);
  console.warn('Trimmed getonbrd categories to cap of', MAX);
}

Type guard

function isWithinCategoryCap(entry, cap) {
  return !Array.isArray(entry.categories) || entry.categories.length <= cap;
}

Try / catch

try {
  const jobs = await getonbrdProvider.fetch(entry, ctx);
} catch (e) {
  if (/getonbrd: \d+ categories configured/.test(String(e.message))) {
    console.warn('Too many categories for', entry.name, '— reduce to the cap and rescan');
    return [];
  }
  throw e;
}

Prevention

When it happens

Trigger: A portal entry listing more than MAX_CATEGORIES valid, deduplicated slugs — e.g. copying the full getonbrd category index into one entry.

Common situations: Users trying to scan 'everything' at once; merging configs from multiple sources that concatenate category lists; forgetting dedup happens before the check (duplicates don't save you).

Related errors


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