santifer/career-ops · error · Error

nofluffjobs: careers_url or api must be a trusted…

Error message

nofluffjobs: careers_url or api must be a trusted nofluffjobs.com URL

What it means

The nofluffjobs provider's fetch() first runs detectUrl(entry) to confirm the entry actually points at a trusted nofluffjobs.com URL (careers_url or api). If detection fails — no URL configured, or one that fails the assert — fetch throws this error instead of attempting a request. It signals a configuration problem, not a network problem.

Solutions

  1. Add a valid https:// nofluffjobs.com careers_url or api field to the entry in portals.yml
  2. Fix the field-name typo so detectUrl can find the URL (careers_url / api)
  3. If the company is not on NoFluffJobs, route the entry to the correct provider instead
  4. Run detect() on the entry first if you need to conditionally dispatch to this provider

Example fix

// before
{ company: 'Acme' } // no url -> fetch throws
// after
{ company: 'Acme', careers_url: 'https://nofluffjobs.com/api/search/posting' }
Defensive patterns

Strategy: validation

Validate before calling

if (!nofluffjobs.detect(entry)) {
  throw new Error(`${entry.company}: no nofluffjobs careers_url/api configured`);
}
await nofluffjobs.fetch(entry, ctx);

Type guard

function hasTrustedNoFluffUrl(entry) {
  const u = entry.api || entry.careers_url || '';
  try {
    const p = new URL(u);
    return p.protocol === 'https:' && p.hostname.endsWith('nofluffjobs.com');
  } catch { return false; }
}

Try / catch

try {
  await nofluffjobs.fetch(entry, ctx);
} catch (e) {
  if (String(e.message).includes('must be a trusted nofluffjobs.com URL')) {
    log.warn(`${entry.company} is not configured for nofluffjobs; dispatch to another provider`);
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the provider's fetch() with an entry that has neither careers_url nor api set, has them empty, or has values that fail assertNoFluffUrl (wrong host or non-https).

Common situations: A portals.yml entry missing the url/api fields; the entry was intended for a different provider (Greenhouse/Lever) and has no NoFluffJobs URL; field name typo ('career_url' instead of 'careers_url'); URL set to another domain.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at providers/nofluffjobs.mjs:138

        url: `${JOB_BASE}${slug}`,
        company,
        location: normalizeLocation(posting),
        postedAt: postedAtMillis(posting.posted),
      };
    })
    .filter(Boolean);
}

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

  detect(entry) {
    return detectUrl(entry);
  },

  async fetch(entry, ctx) {
    if (!detectUrl(entry)) throw new Error('nofluffjobs: careers_url or api must be a trusted nofluffjobs.com URL');

    const maxPages = Number(entry.max_pages || MAX_PAGES);
    const jobs = [];
    const seen = new Set();

    for (let pageTo = 1; pageTo <= maxPages; pageTo++) {
      const { url, body } = buildRequest(entry, pageTo);
      const json = await ctx.fetchJson(url, {
        method: 'POST',
        body: JSON.stringify(body),
        headers: {
          accept: 'application/json, text/plain, */*',
          'content-type': 'application/infiniteSearch+json',
        },
        redirect: 'error',
      });
      for (const job of parseNoFluffJobsResponse(json)) {
        if (seen.has(job.url)) continue;

View on GitHub (pinned to aac998c7ed)