santifer/career-ops · error · Error
nodesk: invalid URL
Error message
nodesk: invalid URL: ${url} What it means
The nodesk provider validates every URL it is given before use. This error is thrown by assertNodeskUrl when the input string cannot be parsed as a URL at all — i.e. new URL(url) throws (missing scheme, whitespace, malformed syntax). It fails fast so a bad config value never reaches the network layer.
Solutions
- Fix the URL string in the config/source so it is a complete absolute URL starting with https://
- Trim whitespace and remove newlines/comments accidentally included in the config value
- Check for unset variables/empty strings being passed in; add a default or an early check
- If the entry should not point at nodesk at all, remove it from the provider's input instead of forcing it through
Example fix
// before
assertNodeskUrl(process.env.NODESK_URL);
// after
const raw = (process.env.NODESK_URL || '').trim();
if (!raw) throw new Error('NODESK_URL is not set');
assertNodeskUrl(raw.startsWith('http') ? raw : `https://${raw}`); Defensive patterns
Strategy: validation
Validate before calling
function isParsableUrl(u) { try { new URL(u); return true; } catch { return false; } }
if (!isParsableUrl(url)) throw new Error(`skipping entry: not a URL: ${url}`); Type guard
function isAbsoluteUrl(u) {
if (typeof u !== 'string' || u.length === 0) return false;
try { const p = new URL(u); return !!p.protocol && !!p.hostname; } catch { return false; }
} Try / catch
try {
useNodesk(url);
} catch (e) {
if (String(e.message).startsWith('nodesk: invalid URL')) {
log.warn(`Skipping bad URL: ${url}`);
return null;
}
throw e;
} Prevention
- Validate all URLs at config-load time, before any provider runs
- Always store full absolute URLs with explicit https:// scheme in config files
- Trim string values read from env vars and CLI args before use
- Write a startup lint that reports every unparseable careers_url entry instead of failing mid-run
When it happens
Trigger: Calling assertNodeskUrl (directly or via the nodesk provider's detect/fetch path) with a string that fails the URL constructor: an empty string, 'nodesk.com/jobs' without a scheme, 'https:/wrong', or a value containing spaces or control characters.
Common situations: A careers_url in portals.yml missing the 'https://' prefix; an env-var or CLI argument that is empty because it was never set; hand-edited config introducing a stray character or truncating the URL; template placeholders left unfilled ('${URL}').
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
- garena: is not a usable URL segment
- landingjobs: invalid URL
- larajobs: invalid URL
- lever: invalid URL
- nofluffjobs: invalid URL
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/521492b53f9788db.
Report an issue: GitHub.
Appendix: source
Thrown at providers/nodesk.mjs:21
/** @typedef {import('./_types.js').Provider} Provider */
// NoDesk provider - board-wide RSS feed
// (https://nodesk.co/remote-jobs/index.xml). The feed is public, no-auth,
// and XML, so it is parsed in-process with the same tiny tag extractor
// approach as providers/personio.mjs rather than adding an XML dependency.
//
// Wire in via a `job_boards:` entry with `provider: nodesk`.
const FEED_URL = 'https://nodesk.co/remote-jobs/index.xml';
const TRUSTED_HOST = 'nodesk.co';
/** @param {string} url */
function assertNodeskUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`nodesk: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`nodesk: URL must use HTTPS: ${url}`);
if (parsed.hostname !== TRUSTED_HOST) {
throw new Error(`nodesk: untrusted hostname "${parsed.hostname}" - must be ${TRUSTED_HOST}`);
}
return url;
}
// NaN-safe Date.parse - `|| undefined` would also coerce a valid epoch 0.
function toEpochMs(value) {
if (!value) return undefined;
const parsed = Date.parse(value);
return Number.isNaN(parsed) ? undefined : parsed;
}
function fallbackCompany(entry) {
return typeof entry?.name === 'string' && entry.name.trim() ? entry.name.trim() : 'NoDesk';
}View on GitHub (pinned to aac998c7ed)