santifer/career-ops · error · Error

himalayas: invalid URL

Error message

himalayas: invalid URL: ${url}

What it means

assertHimalayasUrl validates URLs before the Himalayas provider uses them. If the string cannot be parsed by new URL(), this error is thrown. It fails fast on malformed input so no network request is attempted with a broken URL.

Solutions

  1. Fix the malformed URL shown in the message (usually add the https:// scheme).
  2. Prefer the built-in FEED_URL — only override via config if you really need a custom feed URL.
  3. Add a startup config check that runs new URL() on every configured URL before scanning.
  4. Watch for blank env/config values that make the URL an empty string.

Example fix

// before
const url = process.env.HIMALAYAS_FEED_URL || ''; // '' -> invalid URL
// after
const url = process.env.HIMALAYAS_FEED_URL || FEED_URL;
Defensive patterns

Strategy: validation

Validate before calling

function isValidHimalayasUrl(url) {
  try { new URL(url); return true; } catch { return false; }
}
if (!isValidHimalayasUrl(configuredUrl)) throw new Error(`bad himalayas url: ${configuredUrl}`);

Type guard

const isParseableUrl = (s) => { try { return Boolean(new URL(s)); } catch { return false; } };

Try / catch

try {
  await provider.fetch(entry, ctx);
} catch (err) {
  if (/himalayas: invalid URL/.test(err.message)) {
    console.error(`Fix himalayas URL in config: ${err.message}`);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling assertHimalayasUrl with an empty string, a URL missing its scheme (himalayas.app/jobs/api), a URL containing whitespace, or otherwise unparsable text from config.

Common situations: portals.yml/api overrides for the Himalayas feed typed without https://, env-var interpolation yielding an empty value, or a copy-paste that truncated the URL.

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


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/88acc97f7cd4a2f9. Report an issue: GitHub.

Appendix: source

Thrown at providers/himalayas.mjs:20

/** @typedef {import('./_types.js').Provider} Provider */

// Himalayas provider - board-wide remote jobs API
// (https://himalayas.app/jobs/api?limit=50). Returns { jobs: [...] }. The
// full feed is fetched so scan.mjs's title_filter / location_filter can do
// the local gating consistently with other zero-token board providers.
//
// Wire in via a `job_boards:` entry with `provider: himalayas`.

const FEED_URL = 'https://himalayas.app/jobs/api?limit=50';
const TRUSTED_HOST = 'himalayas.app';

/** @param {string} url */
function assertHimalayasUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error(`himalayas: invalid URL: ${url}`);
  }
  if (parsed.protocol !== 'https:') throw new Error(`himalayas: URL must use HTTPS: ${url}`);
  if (parsed.hostname !== TRUSTED_HOST) {
    throw new Error(`himalayas: untrusted hostname "${parsed.hostname}" - must be ${TRUSTED_HOST}`);
  }
  return url;
}

function cleanText(value) {
  return typeof value === 'string' ? value.trim() : '';
}

function cleanHimalayasUrl(value) {
  const raw = cleanText(value);
  if (!raw) return '';
  try {
    const parsed = new URL(raw);
    const host = parsed.hostname.toLowerCase();

View on GitHub (pinned to aac998c7ed)