santifer/career-ops · error · Error
nofluffjobs: untrusted hostname
Error message
nofluffjobs: untrusted hostname "${parsed.hostname}" — must be nofluffjobs.com What it means
assertNoFluffUrl restricts hostnames to the ALLOWED_HOSTS set (nofluffjobs.com and its official API hosts). This error is thrown when parsed.hostname is not in that set, blocking third-party, look-alike, or typo'd domains from being queried through this provider.
Solutions
- Use a hostname that is in ALLOWED_HOSTS (check the constant at the top of providers/nofluffjobs.mjs for the exact list)
- If a regional variant is legitimately needed, add it to ALLOWED_HOSTS deliberately and review the change
- Move entries for other companies/providers to their correct provider config
- Fix typos and stray subdomains in the configured URL
Example fix
// before
assertNoFluffUrl('https://jobs.example.com/api');
// after
assertNoFluffUrl('https://nofluffjobs.com/api/search/posting'); Defensive patterns
Strategy: validation
Validate before calling
const parsed = new URL(url);
if (!ALLOWED_HOSTS.has(parsed.hostname)) throw new Error(`host not allowed: ${parsed.hostname}`); Type guard
function isAllowedHost(u, allowed) {
try { return allowed.has(new URL(u).hostname); } catch { return false; }
} Try / catch
try {
await nofluffjobs.fetch(entry, ctx);
} catch (e) {
if (String(e.message).startsWith('nofluffjobs: untrusted hostname')) {
log.warn(`Entry for ${entry.company} is not a nofluffjobs.com URL; reassign to correct provider`);
return null;
}
throw e;
} Prevention
- Run node audit-portals.mjs after editing provider URLs to catch wrong-entity boards
- Check ALLOWED_HOSTS before adding regional or subdomain variants
- Keep provider-specific URLs under their own provider config keys
- Never append a trusted hostname to an untrusted domain — validate the full host
When it happens
Trigger: A careers_url/api entry whose hostname is not in ALLOWED_HOSTS — e.g. 'www.nofluffjobs.de' if only the .com host is allowed, a country subdomain, a staging host, or an entirely different company's board.
Common situations: Copy-paste from another provider's config; regional TLD variants (nofluffjobs.pl/hu/de) not in the allowlist; host renamed after a vendor change; typo like 'nofluffjobs.com.evil.io'.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- nodesk: untrusted hostname
- flowxtra: untrusted hostname
- getonbrd: untrusted hostname
- glints: untrusted hostname
- jobbankca: untrusted hostname
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/cb8655ec43900de4.
Report an issue: GitHub.
Appendix: source
Thrown at providers/nofluffjobs.mjs:23
// It intentionally returns only the core scanner job fields; richer skill and
// salary metadata can be added later if the provider contract is expanded.
const ALLOWED_HOSTS = new Set(['nofluffjobs.com']);
const API_URL = 'https://nofluffjobs.com/api/search/posting';
const JOB_BASE = 'https://nofluffjobs.com/pl/job/';
const PAGE_SIZE = 20;
const MAX_PAGES = 5;
function assertNoFluffUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`nofluffjobs: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`nofluffjobs: URL must use HTTPS: ${url}`);
if (!ALLOWED_HOSTS.has(parsed.hostname)) {
throw new Error(`nofluffjobs: untrusted hostname "${parsed.hostname}" — must be nofluffjobs.com`);
}
return parsed;
}
function detectUrl(entry) {
const url = entry.api || entry.careers_url || '';
if (typeof url !== 'string' || !url.trim()) return null;
try {
return { url: assertNoFluffUrl(url).href };
} catch {
return null;
}
}
function normalizeLocation(posting) {
const parts = [];
if (posting?.fullyRemote || posting?.location?.fullyRemote) parts.push('Remote');
if (Array.isArray(posting?.location?.places)) {View on GitHub (pinned to aac998c7ed)