santifer/career-ops · error · Error
landingjobs: invalid URL: ${url}
Error message
landingjobs: invalid URL: ${url} What it means
Thrown by assertLandingUrl() when new URL(url) throws — the input is not a parseable URL. This is the first guard in the landing.jobs URL validator (protocol and hostname checks follow). The validator is the chokepoint for any landing.jobs URL the provider builds or accepts.
Source
Thrown at providers/landingjobs.mjs:26
// created_at, type, tags, gross_salary_low, gross_salary_high, ... }
//
// NOTE: the v1 feed carries no company-name field — the employer slug only
// appears in the posting URL path (`https://landing.jobs/at/<slug>/<job>`), so
// `company` is derived best-effort from that slug (humanized) and falls back to
// the portal entry name. The whole active set is returned in one call.
//
// Wire in via a `job_boards:` entry with `provider: landingjobs`.
const FEED_URL = 'https://landing.jobs/api/v1/jobs';
const TRUSTED_HOST = 'landing.jobs';
/** @param {string} url */
function assertLandingUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`landingjobs: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`landingjobs: URL must use HTTPS: ${url}`);
if (parsed.hostname !== TRUSTED_HOST) {
throw new Error(`landingjobs: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_HOST}`);
}
return url;
}
// NaN-safe Date.parse.
function toEpochMs(value) {
if (typeof value !== 'string' || !value) return undefined;
const parsed = Date.parse(value);
return Number.isNaN(parsed) ? undefined : parsed;
}
/**
* Derive a best-effort company name from a Landing.jobs posting URL.
* Posting URLs are `https://landing.jobs/at/<slug>/<job>`; the `<slug>` isView on GitHub (pinned to 9b17a8ac97)
Solutions
- Set the url field to a full https://landing.jobs/... URL.
- Verify the YAML entry is quoted correctly and is a non-empty string.
- Confirm the value is a string before it reaches the validator.
Example fix
# before acme: provider: landingjobs api: landing.jobs/api/v1/jobs # after acme: provider: landingjobs api: https://landing.jobs/api/v1/jobs
Defensive patterns
Strategy: validation
Validate before calling
function isParseableUrl(url) {
try { new URL(url); return true; } catch { return false; }
}
for (const e of landingjobsEntries) {
const u = e.api || e.careers_url;
if (typeof u !== 'string' || !u.trim() || !isParseableUrl(u)) {
console.warn(`landingjobs ${e.name}: url missing or unparseable`);
}
} Type guard
/** @param {string} url @returns {boolean} */
function isParseableUrl(url) {
try { new URL(url); return true; } catch { return false; }
} Prevention
- Require a full https:// URL for every landingjobs entry.
- Lint config entries for empty or scheme-less URLs.
- Quote YAML string values to avoid type-coercion issues.
When it happens
Trigger: A careers_url or api field that is empty, whitespace-only, lacks a scheme, or contains characters that break the URL parser (spaces, unbalanced brackets); a non-string value passed where a URL string is expected.
Common situations: A portals.yml entry with a blank or unquoted url; a copy-paste that dropped the https:// prefix; a YAML parsing quirk that produced a non-string.
Related errors
- landingjobs: URL must use HTTPS: ${url}
- flowxtra: untrusted hostname "${parsed.hostname}" — must be
- gem: invalid URL: ${url}
- gem: URL must use HTTPS: ${url}
- gem: untrusted hostname "${parsed.hostname}" — must be one o
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/8f4c9e0c56b3216a.
Report an issue: GitHub.