santifer/career-ops · error · Error
4dayweek: invalid URL: ${url}
Error message
4dayweek: invalid URL: ${url} What it means
assertFourDayUrl() in providers/4dayweek.mjs is an SSRF/allowlist guard: before the provider fetches or links any URL, it parses it with new URL() and throws 'invalid URL' if parsing fails. This catches malformed strings — missing scheme, spaces, typos — before they reach fetch.
Source
Thrown at providers/4dayweek.mjs:53
try {
const parsed = new URL(value);
if (parsed.protocol === 'https:' && parsed.hostname === TRUSTED_HOST) {
return { url: FEED_BASE };
}
} catch {
// Ignore malformed URLs; another provider may still claim the entry.
}
}
return null;
}
/** @param {string} url */
function assertFourDayUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`4dayweek: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`4dayweek: URL must use HTTPS: ${url}`);
if (parsed.hostname !== TRUSTED_HOST) {
throw new Error(`4dayweek: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_HOST}`);
}
return url;
}
/** Resolve the page cap: a positive integer `max_pages` on the entry, capped. */
function resolveMaxPages(entry) {
const v = entry?.max_pages;
if (Number.isInteger(v) && v > 0) return Math.min(v, MAX_PAGES_CAP);
return DEFAULT_MAX_PAGES;
}
// NaN-safe: posted is epoch SECONDS → ms; anything non-finite yields undefined.
function toEpochMs(seconds) {
return Number.isFinite(seconds) ? seconds * 1000 : undefined;View on GitHub (pinned to 1696bec4d0)
Solutions
- Print/log the exact url value at the call site — the message already interpolates it — and look for undefined/empty/trailing whitespace.
- Fix the source entry (portals.yml, feed config) so it is an absolute URL starting with https://4dayweek.io/...
- If the URL comes from user input, trim() it and validate with new URL() before calling the provider.
- Ensure the entry's URL field actually exists (not undefined) — a missing field coerces to the string 'undefined'.
Example fix
// before
provider.check('4dayweek.io/job/123'); // TypeError: invalid URL
// after
provider.check('https://4dayweek.io/job/123'); Defensive patterns
Strategy: validation
Validate before calling
function isValidUrl(url) {
if (typeof url !== 'string') return false;
try { new URL(url); return true; } catch { return false; }
}
if (!isValidUrl(entry.url)) throw new Error(`Skip entry: malformed url ${JSON.stringify(entry.url)}`); Type guard
function isUrlString(v) {
if (typeof v !== 'string' || v.length === 0) return false;
try { new URL(v); return true; } catch { return false; }
} Try / catch
try {
provider.check(url);
} catch (err) {
if (err.message.startsWith('4dayweek: invalid URL')) {
console.warn(`Skipping malformed entry: ${err.message}`);
return null;
}
throw err;
} Prevention
- Always store absolute https:// URLs in provider/feed entries — never bare hostnames.
- trim() and strip surrounding quotes from URLs coming from config or user input.
- Validate all url fields at config-load time (fail fast on the whole file, not per request).
- Watch for undefined interpolated into URLs — check the entry actually has a url key.
When it happens
Trigger: Passing any string that new URL() rejects to the 4dayweek provider's URL assertion path: an empty string, a bare hostname like '4dayweek.io/job/123', a URL with unencoded spaces, or a config entry where the URL field is undefined/null coerced to 'undefined'.
Common situations: portals.yml or a feed entry missing the url field (undefined interpolated into the message); copy-pasted URLs containing trailing whitespace or surrounding quotes; hand-written URLs missing 'https://'; template strings where an upstream variable was empty.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- a16z-speedrun-talent: invalid URL: ${url}
- 4dayweek: URL must use HTTPS: ${url}
- a16z-speedrun-talent: URL must use HTTPS: ${url}
- oraclecloud: untrusted hostname "${parsed.hostname}" — must
- personio: untrusted hostname "${parsed.hostname}" — must mat
AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01).
Data as JSON: /api/errors/e035c37079e0b31a.
Report an issue: GitHub.