santifer/career-ops · error · Error
smartrecruiters: invalid URL: ${url}
Error message
smartrecruiters: invalid URL: ${url} What it means
assertSmartRecruitersUrl throws this when new URL(url) raises — the string is not a parseable absolute URL. This is the structural guard preceding the HTTPS and hostname-allowlist checks. smartrecruiters builds API URLs from a resolved slug and the fixed api.smartrecruiters.com host, so a raw parse failure typically indicates a malformed constructed URL or a bad external input.
Source
Thrown at providers/smartrecruiters.mjs:20
/** @typedef {import('./_types.js').Provider} Provider */
// SmartRecruiters provider — hits the public postings API.
// Auto-detects from careers_url pattern
// `https://(careers|jobs).smartrecruiters.com/<slug>`. A tracked_companies
// entry can also set `provider: smartrecruiters` explicitly to bypass
// detection (useful when the public careers URL is a branded custom domain).
const ALLOWED_SMARTRECRUITERS_HOSTS = new Set(['api.smartrecruiters.com']);
const SR_CAREERS_HOSTS = new Set(['careers.smartrecruiters.com', 'jobs.smartrecruiters.com']);
const SR_PAGE_SIZE = 100;
const SR_MAX_PAGES = 50; // safety cap (5000 postings @ 100/page)
function assertSmartRecruitersUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`smartrecruiters: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`smartrecruiters: URL must use HTTPS: ${url}`);
if (!ALLOWED_SMARTRECRUITERS_HOSTS.has(parsed.hostname)) {
throw new Error(`smartrecruiters: untrusted hostname "${parsed.hostname}" — must be one of: ${[...ALLOWED_SMARTRECRUITERS_HOSTS].join(', ')}`);
}
return url;
}
function resolveSlug(entry) {
// entry.api takes precedence over careers_url (mirrors greenhouse/ashby) so a
// branded page (e.g. https://jobs.continental.com) can stay as careers_url
// while the SmartRecruiters slug is pinned via
// api: https://careers.smartrecruiters.com/<slug> in portals.yml.
for (const raw of [entry.api, entry.careers_url]) {
if (typeof raw !== 'string' || !raw) continue;
let parsed;
try {
parsed = new URL(raw);View on GitHub (pinned to 9b17a8ac97)
Solutions
- Log the URL string passed into the guard to identify the malformation.
- Verify the slug was resolved to a non-empty value before URL construction.
- Ensure the API URL is built from the documented base (https://api.smartrecruiters.com/v1/companies/<slug>/postings).
- Strip whitespace and validate with new URL() before invoking the provider.
Example fix
// before
assertSmartRecruitersUrl(slug); // slug is a bare token, not a URL
// after
assertSmartRecruitersUrl(`https://api.smartrecruiters.com/v1/companies/${encodeURIComponent(slug)}/postings`); Defensive patterns
Strategy: validation
Validate before calling
function isParseableUrl(s) {
try { new URL(s); return true; } catch { return false; }
}
// smartrecruiters builds API URLs from a slug — ensure the slug is non-empty
if (!slug || typeof slug !== 'string') {
throw new Error('smartrecruiters: empty slug — cannot build API URL');
}
const apiUrl = `https://api.smartrecruiters.com/v1/companies/${encodeURIComponent(slug)}/postings`;
if (!isParseableUrl(apiUrl)) throw new Error('smartrecruiters: built URL is invalid'); Type guard
null
Try / catch
try {
await provider.fetch(entry, ctx);
} catch (e) {
if (/smartrecruiters: invalid URL/.test(e.message)) {
console.error(`[bug] smartrecruiters URL construction broken — check slug resolution`);
} else throw e;
} Prevention
- Ensure the slug resolves to a non-empty string before building the API URL.
- Unit-test the URL builder for the smartrecruiters provider.
- Validate the built URL parses before invoking the provider.
When it happens
Trigger: The URL passed in has no protocol, contains illegal characters, or is an empty/partial string that the URL constructor rejects.
Common situations: The slug resolution produced an empty string, yielding a malformed API URL; an external caller passed a non-URL value; a config field contained whitespace or smart quotes.
Related errors
- recruitee: invalid URL: ${url}
- remotli: invalid URL: ${url}
- rippling: invalid URL: ${url}
- smartrecruiters: URL must use HTTPS: ${url}
- pinpoint: untrusted hostname "${parsed.hostname}" — must mat
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/afbb8898bf94e4bc.
Report an issue: GitHub.