santifer/career-ops · error · Error
pythonorg: URL must use HTTPS
Error message
pythonorg: URL must use HTTPS: ${url} What it means
assertPythonOrgUrl rejects any URL whose protocol is not https:. The python.org feed provider only talks to the HTTPS endpoint (the feed is public at https://www.python.org/jobs/feed/rss/), so an http: or other-scheme URL is refused even if it is otherwise well-formed. This blocks accidental plaintext fetching and SSRF-style scheme abuse (file:, javascript:, etc.).
Solutions
- Change the URL scheme to https: (e.g. 'https://www.python.org/jobs/feed/rss/') in the config or call site
- For local testing, stub ctx/fetch layer rather than pointing the provider at an http:// URL
- If you control the caller, validate the scheme before invoking: new URL(url).protocol === 'https:'
- Confirm no middleware rewrites or normalizes the configured URL to http
Example fix
// before
assertPythonOrgUrl('http://www.python.org/jobs/feed/rss/');
// after
assertPythonOrgUrl('https://www.python.org/jobs/feed/rss/'); Defensive patterns
Strategy: validation
Validate before calling
function isHttpsUrl(url) {
try { return new URL(url).protocol === 'https:'; } catch { return false; }
}
// if (!isHttpsUrl(cfg.feedUrl)) throw new Error('pythonorg feedUrl must be https'); Type guard
function isHttpsPythonOrgUrl(value) {
if (typeof value !== 'string') return false;
try { const u = new URL(value); return u.protocol === 'https:' && u.hostname.endsWith('python.org'); } catch { return false; }
} Try / catch
try {
assertPythonOrgUrl(cfg.feedUrl);
} catch (e) {
if (e.message.startsWith('pythonorg: URL must use HTTPS')) {
console.error(`Config error: ${cfg.feedUrl} must use https:// — fix the scheme`);
} else throw e;
} Prevention
- Default to https:// in every config URL; never write http:// even for 'known safe' hosts
- Add a startup validation pass that rejects non-https board URLs before any network work
- Don't point providers at local http:// mock servers — stub the fetch layer in tests instead
- Check for middleware/normalizers that might downgrade or rewrite the scheme
When it happens
Trigger: Calling assertPythonOrgUrl with a URL whose parsed.protocol !== 'https:' — typically 'http://www.python.org/jobs/feed/rss/', but also file: or custom-scheme URLs that pass URL parsing.
Common situations: Config entry written with http:// out of habit; a redirect/downgrade helper rewriting https to http; tests using a local http:// mock server URL directly instead of stubbing the fetch; copying an insecure mirror link.
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-22).
Data as JSON: /api/errors/48c4f9882db75800.
Report an issue: GitHub.
Appendix: source
Thrown at providers/pythonorg.mjs:28
// The feed is public, no-auth, and RSS 2.0 XML.
//
// Each <item> exposes <title> (typically "{Role}, {Company}"), <link>,
// and <description> (the first line typically contains the location).
//
// Wire in via a `job_boards:` entry with `provider: pythonorg`.
const FEED_URL = 'https://www.python.org/jobs/feed/rss/';
const TRUSTED_HOST = 'python.org';
/** @param {string} url */
export function assertPythonOrgUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`pythonorg: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`pythonorg: URL must use HTTPS: ${url}`);
const host = parsed.hostname.toLowerCase();
const trusted = host === TRUSTED_HOST || host.endsWith(`.${TRUSTED_HOST}`);
if (!trusted) {
throw new Error(`pythonorg: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_HOST}`);
}
return url;
}
// NaN-safe Date.parse — `|| undefined` would also coerce a valid epoch 0.
function toEpochMs(value) {
if (!value) return undefined;
const parsed = Date.parse(value);
return Number.isNaN(parsed) ? undefined : parsed;
}
function fallbackCompany(entry) {
return typeof entry?.name === 'string' && entry.name.trim() ? entry.name.trim() : 'Python.org';
}View on GitHub (pinned to e7abd431fc)