santifer/career-ops · error
gem: URL must use HTTPS
Error message
gem: URL must use HTTPS: ${url} What it means
URL scheme guard in the GEM board provider (assertGemUrl): the parsed careers/board URL's protocol is not https:. The URL parsed successfully but uses http: or another scheme; the provider refuses to fetch over a non-HTTPS connection. The input at fault is the careers_url configured for the board.
Solutions
- Change the URL scheme from http:// to https:// in the config entry.
- Verify the host actually serves HTTPS (test with curl -I https://...); most Gem boards do.
- If this is a local/dev stub, use an HTTPS local endpoint or a test double instead of downgrading the scheme.
Example fix
// before
assertGemUrl('http://boards.gem.com/company');
// after
assertGemUrl('https://boards.gem.com/company'); Defensive patterns
Strategy: validation
Validate before calling
if (!u.startsWith('https://')) throw new Error(`Gem URLs must be https://, got: ${u}`); Type guard
const isHttpsUrl = (u) => { try { return new URL(u).protocol === 'https:'; } catch { return false; } }; Try / catch
try { assertGemUrl(url); } catch (e) { if (e.message.includes('must use HTTPS')) throw new Error(`Fix scheme for ${url}: use https://`); throw e; } Prevention
- Never configure http:// for external job boards
- Grep configs for 'http://' on a schedule
- Use HTTPS-everywhere defaults in templates
- Test staging boards over HTTPS instead of downgrading the scheme
When it happens
Trigger: Passing 'http://boards.gem.com/...' or any ftp:/ws:/file: scheme URL into assertGemUrl, or configuring a board entry whose api/careers URL starts with http:// in portals.yml.
Common situations: Copying an HTTP link from an older config or docs snippet; a redirect target recorded as http://; internal staging boards configured with http for local testing and forgotten.
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
- breezy: URL must use HTTPS
- builtin: URL must use HTTPS
- careerviet: URL must use HTTPS
- comeet: URL must use HTTPS
- arbeitnow: URL must use HTTPS
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/5f6c85165ae48efe.
Report an issue: GitHub.
Appendix: source
Thrown at providers/gem.mjs:125
function buildJobDescriptionText(posting) {
const intro = htmlToText(posting?.jobPostSectionHtml?.introHtml);
const body = htmlToText(posting?.descriptionHtml);
const outro = htmlToText(posting?.jobPostSectionHtml?.outroHtml);
const compensation = htmlToText(posting?.compensationHtml);
const text = [intro, body, outro].filter(Boolean).join('\n\n');
return compensation ? [text, `Compensation: ${compensation}`].filter(Boolean).join('\n\n') : text;
}
/** @param {string} url */
function assertGemUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`gem: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`gem: URL must use HTTPS: ${url}`);
if (!ALLOWED_GEM_HOSTS.has(parsed.hostname))
throw new Error(`gem: untrusted hostname "${parsed.hostname}" — must be one of: ${[...ALLOWED_GEM_HOSTS].join(', ')}`);
return url;
}
/** Resolve an explicitly pinned URL for Gem's documented REST job-board API. */
function resolveRestApiUrl(entry) {
const raw = typeof entry.api === 'string' ? entry.api : '';
if (!raw) return null;
let parsed;
try {
parsed = new URL(raw);
} catch {
return null;
}
if (parsed.protocol !== 'https:' || parsed.hostname !== 'api.gem.com') return null;
if (!/^\/job_board\/v0\/[^/?#]+\/job_posts\/?$/.test(parsed.pathname)) return null;
return parsed;View on GitHub (pinned to aac998c7ed)