santifer/career-ops · warning

portals.yml: an enabled entry has no name

Error message

portals.yml: an enabled entry has no name (careers_url: ${e.careers_url || 'none'}) — it cannot be provider-checked; give it a name

What it means

verify-pipeline.mjs Check 15 warns about malformed portals.yml entries: an entry is enabled (enabled !== false) but has no usable `name` string. Such an entry can't be claimed by any provider, so it is excluded from provider checking and from the 'All N entries resolve' success count — it would silently never scan.

Solutions

  1. Open portals.yml and give the listed entry a non-empty `name:` string
  2. Ensure `name` is a plain scalar, not null or a nested block
  3. Re-run verify-pipeline.mjs; the entry should then receive a provider check
  4. Optionally run `node audit-portals.mjs` afterwards to confirm the board actually answers

Example fix

# before
- careers_url: https://boards.greenhouse.io/acme
  enabled: true
# after
- name: Acme
  careers_url: https://boards.greenhouse.io/acme
  enabled: true
Defensive patterns

Strategy: validation

Validate before calling

const malformed = entries.filter(e => e && e.enabled !== false && (typeof e.name !== 'string' || !e.name.trim()));
if (malformed.length) throw new Error('portals.yml entries missing name: ' + malformed.map(e => e.careers_url).join(', '));

Type guard

const hasName = (e) => e && typeof e.name === 'string' && e.name.trim().length > 0;

Prevention

When it happens

Trigger: Running `node verify-pipeline.mjs` after hand-editing portals.yml and adding an entry with a missing name, a name of ""/whitespace, or a name that isn't a string (e.g. a number or a nested map).

Common situations: YAML mistake like writing `name:` with no value; duplicating an entry and deleting the name line; a merge conflict resolved leaving the name out.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-16). Data as JSON: /api/errors/6df69f7595848765. Report an issue: GitHub.

Appendix: source

Thrown at verify-pipeline.mjs:563

    // CODE_ROOT (scan.mjs does the same). Without mergeProviderPlugins() the
    // health check sees only providers/*.mjs and reports every enabled
    // plugin-provider entry as an unknown provider that "never scans", while
    // the scanner resolves and scans it (#4026). No-op for a plugin-free
    // install: mergeProviderPlugins returns before any work when
    // config/plugins.yml is absent.
    const providers = await loadProviders(join(CODE_ROOT, 'providers'));
    await mergeProviderPlugins(providers, { root: CODE_ROOT });
    const { silent, handoff, unknownProvider } = findUnclaimedEntries(entries, providers);

    // findUnclaimedEntries silently skips an entry with no (or blank) `name` —
    // it can't report what it can't label. Without this, that entry vanishes
    // from silent/handoff/unknownProvider entirely, and the enabled count
    // below (which doesn't share the same eligibility rule) would still
    // include it — so a malformed entry never gets a provider check AND the
    // "All N entries resolve" success line claims it as resolved anyway.
    const malformed = entries.filter(e => e && e.enabled !== false && (typeof e.name !== 'string' || !e.name.trim()));
    for (const e of malformed) {
      warn(`portals.yml: an enabled entry has no name (careers_url: ${e.careers_url || 'none'}) — it cannot be provider-checked; give it a name`);
    }

    for (const e of unknownProvider) {
      error(`portals.yml: "${e.name}" sets an unknown provider — ${e.error}. The entry never scans (see providers/ for valid ids)`);
    }
    for (const e of silent) {
      warn(`portals.yml: "${e.name}" is enabled but no provider claims ${e.careers_url || 'its careers_url'} — scan.mjs skips it on every run without naming it (run node audit-portals.mjs)`);
    }
    if (silent.length === 0 && unknownProvider.length === 0 && malformed.length === 0) {
      const enabled = entries.filter(e => e && e.enabled !== false).length;
      ok(handoff.length > 0
        ? `All ${enabled - handoff.length} scannable portals.yml entries resolve to a provider (${handoff.length} on websearch handoff)`
        : `All ${enabled} enabled portals.yml entries resolve to a provider`);
    }
  } catch (err) {
    warn(`Portal coverage check could not run: ${err.message}`);
  }
}

View on GitHub (pinned to e7abd431fc)