santifer/career-ops · error
comeet: URL path must be the careers-api endpoint
Error message
comeet: URL path must be the careers-api endpoint: ${redactToken(url)} What it means
assertComeetUrl validates that a URL given to the Comeet provider points at Comeet's official API host over HTTPS and uses the /careers-api/ path prefix. The library throws this error when the URL passes the hostname and protocol checks but its pathname does not start with /careers-api/, meaning the provider would hit an unknown endpoint on www.comeet.co. It fails fast to prevent fetching from a path the parser does not understand.
Solutions
- Change the entry's api: value to the full careers-api positions URL, e.g. https://www.comeet.co/careers-api/v2.1/company/{company}/positions?token=...
- Check the pathname begins with /careers-api/ (a quick new URL(api).pathname.startsWith('/careers-api/') check before configuring).
- If you only have the public jobs page, locate or derive the careers-api endpoint Comeet's page calls and use that instead of the page URL.
- Keep the per-tenant ?token= in the URL but be aware errors redact it — if the redacted log hides the path, inspect the entry config directly.
Example fix
// before api: https://www.comeet.com/mycompany/jobs // after api: https://www.comeet.co/careers-api/v2.1/company/mycompany/positions?token=XXXX
Defensive patterns
Strategy: validation
Validate before calling
function isComeetApiUrl(u) { try { const p = new URL(u); return p.protocol === 'https:' && p.hostname === 'www.comeet.co' && p.pathname.startsWith('/careers-api/'); } catch { return false; } }
if (!isComeetApiUrl(entry.api)) throw new Error(`entry ${entry.name}: api must be a comeet /careers-api/ URL`); Type guard
const isComeetApiUrl = (u) => { try { const p = new URL(u); return p.protocol === 'https:' && p.hostname === 'www.comeet.co' && p.pathname.startsWith('/careers-api/'); } catch { return false; } }; Prevention
- Always copy the careers-api positions URL, never the public jobs page URL
- Validate the URL shape in a pre-scan config linter before adding entries to portals.yml
- Keep the ?token= in place — errors redact it, but fetch needs it
- Compare against a known-working comeet entry when onboarding a new company
When it happens
Trigger: Calling fetch (or assertComeetUrl directly) with an entry whose api: URL is a Comeet careers *page* URL (e.g. https://www.comeet.com/company/jobs or /careers/...) or a bare host URL rather than the careers-api positions endpoint (e.g. https://www.comeet.co/careers-api/...).
Common situations: Copying the public jobs-page URL from a company's careers site instead of the underlying careers-api positions URL; hand-trimming the path when configuring portals.yml; a Comeet URL scheme change or migration leaving a stale path.
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
- flowxtra: URL must use HTTPS
- oraclecloud: untrusted hostname
- personio: untrusted hostname
- pinpoint: untrusted hostname
- breezy: invalid URL
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/1d07f3fa4bacb17b.
Report an issue: GitHub.
Appendix: source
Thrown at providers/comeet.mjs:40
} catch {
return false;
}
return parsed.protocol === 'https:' && parsed.hostname === COMEET_API_HOST && parsed.pathname.startsWith('/careers-api/');
}
/** @param {string} url */
function assertComeetUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`comeet: invalid URL: ${redactToken(url)}`);
}
if (parsed.protocol !== 'https:') throw new Error(`comeet: URL must use HTTPS: ${redactToken(url)}`);
if (parsed.hostname !== COMEET_API_HOST)
throw new Error(`comeet: untrusted hostname "${parsed.hostname}" — must be ${COMEET_API_HOST}`);
if (!parsed.pathname.startsWith('/careers-api/'))
throw new Error(`comeet: URL path must be the careers-api endpoint: ${redactToken(url)}`);
return url;
}
// Redact the per-tenant ?token= so neither the (informational, possibly-logged)
// DetectHit url nor a thrown validation error carries the secret. Best-effort:
// falls back to a regex strip when the value can't be parsed as a URL.
function redactToken(url) {
try {
const parsed = new URL(url);
if (parsed.searchParams.has('token')) parsed.searchParams.set('token', 'REDACTED');
return parsed.href;
} catch {
return typeof url === 'string' ? url.replace(/([?&]token=)[^&#]*/gi, '$1REDACTED') : url;
}
}
/** @param {import('./_types.js').PortalEntry} entry */
function resolveApiUrl(entry) {View on GitHub (pinned to aac998c7ed)