santifer/career-ops · error
greenhouse: URL must use HTTPS
Error message
greenhouse: URL must use HTTPS: ${url} What it means
assertGreenhouseUrl enforces that every Greenhouse API/board URL uses HTTPS. If the parsed URL has any other protocol (http:, ftp:, etc.), the provider throws this error. This prevents accidentally hitting the Greenhouse API in plaintext and keeps all outbound requests on TLS.
Solutions
- Change the entry's scheme to https:// in portals.yml.
- If you maintain a URL-builder helper, hardcode the https: scheme instead of copying the input scheme.
- Run a config lint that rejects non-https URLs for ATS providers before scanning.
Example fix
// before (portals.yml) api: http://boards-api.greenhouse.io/acme // after api: https://boards-api.greenhouse.io/acme
Defensive patterns
Strategy: validation
Validate before calling
function isHttps(url) {
try { return new URL(url).protocol === 'https:'; } catch { return false; }
}
if (!isHttps(entry.api)) throw new Error(`greenhouse entries must use https: ${entry.api}`); Type guard
const isHttpsUrl = (s) => { try { return new URL(s).protocol === 'https:'; } catch { return false; } }; Try / catch
try {
await provider.fetch(entry, ctx);
} catch (err) {
if (/greenhouse: URL must use HTTPS/.test(err.message)) {
console.error(`Upgrade entry "${entry.name}" to https — see ${err.message}`);
return;
}
throw err;
} Prevention
- Never copy http:// URLs from legacy docs into ATS config.
- Enforce https in any URL-building helper.
- Add a CI check rejecting non-https provider URLs.
- Default to the provider's canonical https API URL.
When it happens
Trigger: A portals.yml api: or careers_url value starting with http:// instead of https://, or a URL built from a base string that had its scheme stripped and re-prefixed as http.
Common situations: Config copied from old documentation that predated HTTPS-only boards, a reverse-proxy note telling you to use http:// for local debugging, or a user-typed URL without scheme defaults mis-resolved to http.
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
- arbeitnow: URL must use HTTPS
- ashby: URL must use HTTPS
- bamboohr: URL must use HTTPS
- breezy: URL must use HTTPS
- builtin: URL must use HTTPS
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/dd769a534f54bd46.
Report an issue: GitHub.
Appendix: source
Thrown at providers/greenhouse.mjs:28
import { htmlToText } from './_html-to-text.mjs';
const ALLOWED_GREENHOUSE_HOSTS = new Set([
'boards-api.greenhouse.io',
'boards.greenhouse.io',
'job-boards.greenhouse.io',
'job-boards.eu.greenhouse.io',
]);
/** @param {string} url */
function assertGreenhouseUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`greenhouse: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`greenhouse: URL must use HTTPS: ${url}`);
if (!ALLOWED_GREENHOUSE_HOSTS.has(parsed.hostname))
throw new Error(`greenhouse: untrusted hostname "${parsed.hostname}" — must be one of: ${[...ALLOWED_GREENHOUSE_HOSTS].join(', ')}`);
return url;
}
/** @param {import('./_types.js').PortalEntry} entry */
function resolveApiUrl(entry) {
if (entry.api) {
assertGreenhouseUrl(entry.api);
return entry.api;
}
const url = entry.careers_url || '';
const match = url.match(/job-boards(?:\.eu)?\.greenhouse\.io\/([^/?#]+)/);
if (match) return `https://boards-api.greenhouse.io/v1/boards/${match[1]}/jobs`;
return null;
}
// NaN-safe Date.parse — `|| undefined` would also coerce a valid epoch 0.View on GitHub (pinned to aac998c7ed)