santifer/career-ops · error
getonbrd: invalid URL
Error message
getonbrd: invalid URL: ${url} What it means
assertGetonbrdUrl validates any URL destined for the Get on Board provider. When the string cannot be parsed by the WHATWG URL constructor (new URL throws on malformed input like missing scheme, spaces, or unescaped characters), the function throws this error. It is the first of three gates (parse, protocol, hostname) guarding against misconfigured or malicious portal entries reaching the fetch layer.
Solutions
- Prefix the URL with the scheme if missing — it must be a full absolute URL like https://www.getonbrd.com/api/v0/categories/programming/jobs
- Trim whitespace and replace smart quotes/line breaks; quote the value in YAML so special characters don't break parsing
- Validate locally with `new URL(value)` (or paste into a browser address bar) before adding it to portals.yml
- If the entry doesn't need a custom URL, remove it and let the provider build the feed URL from the category slug
Example fix
// before careers_url: www.getonbrd.com/api/v0/categories/programming/jobs // after careers_url: https://www.getonbrd.com/api/v0/categories/programming/jobs
Defensive patterns
Strategy: validation
Validate before calling
function isValidAbsoluteUrl(s) { try { new URL(s); return true; } catch { return false; } }
if (!isValidAbsoluteUrl(entry.careers_url)) throw new Error(`entry ${entry.name}: careers_url is not a valid absolute URL`); Type guard
function isHttpUrl(v) { return typeof v === 'string' && (() => { try { return !!new URL(v); } catch { return false; } })(); } Try / catch
try {
assertGetonbrdUrl(url);
} catch (e) {
if (String(e.message).includes('invalid URL')) {
console.error(`Config error: ${url} is not parseable — check scheme and characters`);
return null;
}
throw e;
} Prevention
- Always store full absolute URLs with https:// scheme in portals.yml
- Quote URL values in YAML so special characters don't break parsing
- Run new URL(value) sanity checks in CI on config files
- Avoid pasting URLs with surrounding whitespace or smart quotes
When it happens
Trigger: A portals.yml entry supplies a careers_url or feed URL that is not a syntactically valid absolute URL — e.g. 'getonbrd.com/api/v0/...', 'https//www.getonbrd.com', or a URL containing spaces/unbalanced brackets — and assertGetonbrdUrl is called on it.
Common situations: Hand-edited portals.yml missing the https:// scheme; a URL pasted with trailing whitespace or typographic quotes; template placeholders (${...}) left unsubstituted in config; YAML folding turning a URL into a multi-line string.
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
- glints: invalid URL
- comeet: URL path must be the careers-api endpoint
- consider: needs an https careers_url on a public host
- csod: cannot resolve careersite URL for
- flowxtra: untrusted hostname
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/d5558b9ac288e506.
Report an issue: GitHub.
Appendix: source
Thrown at providers/getonbrd.mjs:81
}
if (!out.length) {
throw new Error('getonbrd: `categories` is empty — omit it to use the "programming" default');
}
if (out.length > MAX_CATEGORIES) {
throw new Error(
`getonbrd: ${out.length} categories configured — cap is ${MAX_CATEGORIES} (each one costs up to max_pages requests)`,
);
}
return out;
}
/** @param {string} url */
function assertGetonbrdUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`getonbrd: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`getonbrd: URL must use HTTPS: ${url}`);
if (parsed.hostname !== TRUSTED_HOST) {
throw new Error(`getonbrd: 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;
}
/**
* Normalize a single Get on Board job (JSON:API resource). Exported for tests.
*View on GitHub (pinned to aac998c7ed)