santifer/career-ops · error · Error

getro: ${entry.name} needs a numeric 'getro_collection' in p

Error message

getro: ${entry.name} needs a numeric 'getro_collection' in portals.yml

What it means

getro.mjs throws this at the top of fetch() when resolveCollection(entry) returns null. resolveCollection requires entry.getro_collection to be present and, after String().trim(), to match /^\d+$/ — a pure-numeric collection id. Getro's API is keyed by a numeric collection_id (the network.id embedded in the board page), so without a valid one the provider cannot build the request URL.

Source

Thrown at providers/getro.mjs:75

  const id = entry.getro_collection;
  if (id == null) return null;
  const s = String(id).trim();
  if (!/^\d+$/.test(s)) return null;
  return s;
}

/** @type {Provider} */
export default {
  id: 'getro',

  detect(entry) {
    const id = resolveCollection(entry);
    return id ? { url: `${API_BASE}/${id}/search/jobs` } : null;
  },

  async fetch(entry, ctx) {
    const id = resolveCollection(entry);
    if (!id) throw new Error(`getro: ${entry.name} needs a numeric 'getro_collection' in portals.yml`);
    const apiUrl = `${API_BASE}/${id}/search/jobs`;
    const maxPages = Number.isInteger(entry.getro_max_pages) && entry.getro_max_pages > 0
      ? Math.min(entry.getro_max_pages, HARD_MAX_PAGES) : DEFAULT_MAX_PAGES;
    const maxAgeDays = Number.isFinite(entry.getro_max_age_days) && entry.getro_max_age_days >= 0
      ? entry.getro_max_age_days : DEFAULT_MAX_AGE_DAYS;
    const cutoffMs = maxAgeDays > 0 ? Date.now() - maxAgeDays * 86_400_000 : 0;

    const out = [];
    let total = Infinity;
    for (let page = 0; page < maxPages && page * HITS_PER_PAGE < total; page++) {
      const json = await ctx.fetchJson(apiUrl, {
        method: 'POST',
        // redirect:'error' — apiUrl is pinned to api.getro.com (https), so a 3xx
        // to a private/metadata IP must not be followed (matches every provider).
        redirect: 'error',
        headers: { 'content-type': 'application/json', accept: 'application/json' },
        body: JSON.stringify({ hitsPerPage: HITS_PER_PAGE, page }),
      });

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Open the Getro board page, view its __NEXT_DATA__ (or network tab), and copy the numeric network.id / collection_id.
  2. Set getro_collection to that integer in portals.yml (e.g. getro_collection: 4283).
  3. Double-check the field name is exactly getro_collection (not collection_id or getro_id).
  4. Ensure the value is a bare integer or a numeric string with no spaces/quotes.

Example fix

# before
- name: b2venture (portfolio)
  provider: getro
  careers_url: https://jobs.b2venture.vc   # no numeric id -> throws

# after
- name: b2venture (portfolio)
  provider: getro
  getro_collection: 4283
  careers_url: https://jobs.b2venture.vc
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight check for a portals.yml entry before invoking the getro provider.
function getroEntryIsValid(entry) {
  if (entry.provider !== 'getro') return true;
  const id = entry.getro_collection;
  if (id == null) return false;
  return /^\d+$/.test(String(id).trim());
}

Prevention

When it happens

Trigger: A portals.yml entry has provider: getro but no getro_collection; getro_collection is a non-numeric string (e.g. a board slug like 'b2venture'); getro_collection is null/undefined; the value is a quoted number that YAML parsed as a string with whitespace; the field was typo'd (e.g. collection_id, getro_id).

Common situations: Operator copies a Getro careers_url but forgets the numeric collection id; operator uses the board's textual slug instead of the numeric network.id; a field-name typo means the real value sits under an unrecognized key; YAML formatting made the number a string that still fails the regex after an accidental non-digit character.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/615824e6b9920c32. Report an issue: GitHub.