santifer/career-ops · error · Error
lever: URL must use HTTPS
Error message
lever: URL must use HTTPS: ${url} What it means
assertLeverUrl rejects any parsed URL whose protocol is not 'https:'. This enforces TLS for all Lever API traffic, protecting postings data and request metadata from plaintext interception or downgrade.
Solutions
- Use https:// in the URL/config entry.
- Search portals.yml and caller code for 'http://' and upgrade each to 'https://'.
- For local testing, use a mock that speaks https or inject a test double for fetch rather than bypassing the assertion.
- Confirm with new URL(u).protocol === 'https:' before the call.
Example fix
// before
assertLeverUrl('http://api.lever.co/v0/postings/acme');
// after
assertLeverUrl('https://api.lever.co/v0/postings/acme'); Defensive patterns
Strategy: validation
Validate before calling
function isHttpsUrl(u) { try { return new URL(u).protocol === 'https:'; } catch { return false; } }
if (!isHttpsUrl(url)) throw new Error(`lever endpoint must be https: ${url}`); Type guard
function isHttpsUrlString(v) { if (typeof v !== 'string') return false; try { return new URL(v).protocol === 'https:'; } catch { return false; } } Try / catch
try {
provider.fetch(entry, ctx);
} catch (e) {
if (e.message.startsWith('lever: URL must use HTTPS')) {
console.warn(`Upgrading to https: ${e.message}`);
return provider.fetch({ ...entry, url: entry.url.replace(/^http:/, 'https:') }, ctx);
}
throw e;
} Prevention
- Always use https:// for api.lever.co endpoints
- CI-check config for http:// URLs
- Test with https mocks rather than weakening the validator
- Copy example URLs from current docs, not old snippets
When it happens
Trigger: Passing a http:// (or ftp:, file:, etc.) URL to assertLeverUrl or the lever provider fetch, e.g. 'http://api.lever.co/v0/postings/acme'.
Common situations: Older config with http:// endpoints, copied example snippets using http, or a local test harness URL written with http://localhost that reaches the production validator.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- a16z-speedrun-talent: URL must use HTTPS
- agentic-jobs: URL must use HTTPS
- collage: URL must use HTTPS
- getonbrd: URL must use HTTPS
- glints: URL must use HTTPS
AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-16).
Data as JSON: /api/errors/706a33e383a14ad8.
Report an issue: GitHub.
Appendix: source
Thrown at providers/lever.mjs:24
// Handles both explicit `api:` URLs and auto-detection from `careers_url`.
const ALLOWED_LEVER_HOSTS = new Set(['api.lever.co', 'api.eu.lever.co']);
// The v0 postings endpoint returns the whole board in one response, with every
// description inlined, so a large board outgrows _http.mjs's 10s default:
// jobgether is 42.8 MB and aborted at 10s on its own (#4177). Same value and
// reasoning as ASHBY_TIMEOUT_MS, the other one-response board-wide ATS feed.
const LEVER_TIMEOUT_MS = 30_000;
/** @param {string} url */
function assertLeverUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`lever: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`lever: URL must use HTTPS: ${url}`);
if (!ALLOWED_LEVER_HOSTS.has(parsed.hostname))
throw new Error(`lever: untrusted hostname "${parsed.hostname}" — must be one of: ${[...ALLOWED_LEVER_HOSTS].join(', ')}`);
return url;
}
/** @param {import('./_types.js').PortalEntry} entry */
function resolveApiUrl(entry) {
// Explicit api: wins — lets an entry keep a human-facing corporate
// careers_url (e.g. https://www.coalfire.com/careers) while still pinning
// the Lever postings board (mirrors greenhouse's api: precedence).
if (entry.api) {
assertLeverUrl(entry.api);
return entry.api;
}
let url;
try {
url = new URL(entry.careers_url || '');
} catch {View on GitHub (pinned to e7abd431fc)