santifer/career-ops · error · Error
nofluffjobs: careers_url or api must be a trusted nofluffjob
Error message
nofluffjobs: careers_url or api must be a trusted nofluffjobs.com URL
What it means
Thrown by nofluffjobs' fetch() when detectUrl(entry) returns null — meaning the entry has no usable api or careers_url that passes the full SSRF guard chain. This is a config-completeness check: fetch() re-validates detect()'s preconditions and refuses to proceed if the entry cannot resolve to a trusted URL. It prevents fetch() from silently doing nothing or hitting an unvalidated URL.
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 9b17a8ac97)
Solutions
- Check the portals.yml entry: it must have either api or careers_url set to a valid https://nofluffjobs.com URL.
- Ensure detect() and fetch() receive the same entry object — if entries are being rebuilt or merged, verify the nofluffjobs entry survives the process.
- If calling fetch() programmatically, call detect(entry) first and skip entries that return null.
Example fix
// before — entry has no usable URL
job_boards:
nofluff:
provider: nofluffjobs
# missing api and careers_url
// after
job_boards:
nofluff:
provider: nofluffjobs
api: 'https://nofluffjobs.com/api/search/posting'
max_pages: 5 Defensive patterns
Strategy: validation
Validate before calling
/** Verify the entry can resolve to a trusted NoFluffJobs URL before fetch. */
function canFetchNoFluff(entry) {
const url = entry.api || entry.careers_url || '';
if (typeof url !== 'string' || !url.trim()) return false;
try {
const p = new URL(url);
return p.protocol === 'https:' && p.hostname === 'nofluffjobs.com';
} catch {
return false;
}
}
if (!canFetchNoFluff(entry)) {
console.warn(`nofluffjobs entry ${entry.name} has no valid URL — skipping`);
continue;
} Type guard
/** @param {import('./_types.js').PortalEntry} entry @returns {boolean} */
function hasValidNoFluffUrl(entry) {
const url = entry.api || entry.careers_url;
return typeof url === 'string' && url.startsWith('https://nofluffjobs.com');
} Try / catch
try {
await nofluffProvider.fetch(entry, ctx);
} catch (err) {
if (String(err.message).includes('must be a trusted nofluffjobs.com URL')) {
console.warn(`skipping ${entry.name}: no valid nofluffjobs URL in config`);
continue;
}
throw err;
} Prevention
- Call detect(entry) before fetch() and skip entries returning null.
- Validate portals.yml entries at load time for required URL fields per provider.
- Ensure config merges preserve the api/careers_url field for nofluffjobs entries.
When it happens
Trigger: detectUrl() returns null when: (1) entry.api and entry.careers_url are both empty/non-string; (2) the URL fails assertNoFluffUrl (wrong scheme, wrong host, unparseable) and detectUrl's catch returns null. If detect() returned non-null but the entry was mutated between detect() and fetch(), or if fetch() is called directly with an unvalidated entry, this fires.
Common situations: A portals.yml entry is missing both api and careers_url fields. The entry has a URL that was valid for a different provider (wrong host). The entry object was constructed programmatically (e.g. by a batch script) without the required URL field. A race condition or config reload changes the entry between detect() and fetch().
Related errors
- nofluffjobs: invalid URL: ${url}
- nofluffjobs: URL must use HTTPS: ${url}
- oraclecloud: cannot derive API URL for ${entry.name}
- personio: cannot derive feed URL for ${entry.name}
- flowxtra: untrusted hostname "${parsed.hostname}" — must be
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/77610c5b9647ed01.
Report an issue: GitHub.