{"record":{"id":"88acc97f7cd4a2f9","repo":"santifer/career-ops","slug":"himalayas-invalid-url-url","errorCode":null,"errorMessage":"himalayas: invalid URL: ${url}","messagePattern":"himalayas: invalid URL: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/himalayas.mjs","lineNumber":20,"sourceCode":"/** @typedef {import('./_types.js').Provider} Provider */\n\n// Himalayas provider - board-wide remote jobs API\n// (https://himalayas.app/jobs/api?limit=50). Returns { jobs: [...] }. The\n// full feed is fetched so scan.mjs's title_filter / location_filter can do\n// the local gating consistently with other zero-token board providers.\n//\n// Wire in via a `job_boards:` entry with `provider: himalayas`.\n\nconst FEED_URL = 'https://himalayas.app/jobs/api?limit=50';\nconst TRUSTED_HOST = 'himalayas.app';\n\n/** @param {string} url */\nfunction assertHimalayasUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`himalayas: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`himalayas: URL must use HTTPS: ${url}`);\n  if (parsed.hostname !== TRUSTED_HOST) {\n    throw new Error(`himalayas: untrusted hostname \"${parsed.hostname}\" - must be ${TRUSTED_HOST}`);\n  }\n  return url;\n}\n\nfunction cleanText(value) {\n  return typeof value === 'string' ? value.trim() : '';\n}\n\nfunction cleanHimalayasUrl(value) {\n  const raw = cleanText(value);\n  if (!raw) return '';\n  try {\n    const parsed = new URL(raw);\n    const host = parsed.hostname.toLowerCase();","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/himalayas.mjs#L2-L38","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the malformed URL shown in the message (usually add the https:// scheme).","Prefer the built-in FEED_URL — only override via config if you really need a custom feed URL.","Add a startup config check that runs new URL() on every configured URL before scanning.","Watch for blank env/config values that make the URL an empty string."],"exampleFix":"// before\nconst url = process.env.HIMALAYAS_FEED_URL || ''; // '' -> invalid URL\n// after\nconst url = process.env.HIMALAYAS_FEED_URL || FEED_URL;","handlingStrategy":"validation","validationCode":"function isValidHimalayasUrl(url) {\n  try { new URL(url); return true; } catch { return false; }\n}\nif (!isValidHimalayasUrl(configuredUrl)) throw new Error(`bad himalayas url: ${configuredUrl}`);","typeGuard":"const isParseableUrl = (s) => { try { return Boolean(new URL(s)); } catch { return false; } };","tryCatchPattern":"try {\n  await provider.fetch(entry, ctx);\n} catch (err) {\n  if (/himalayas: invalid URL/.test(err.message)) {\n    console.error(`Fix himalayas URL in config: ${err.message}`);\n    return;\n  }\n  throw err;\n}","preventionTips":["Use the provider's FEED_URL default instead of hand-typing the feed URL.","Validate configured URLs with new URL() at config load.","Trim config values and guard against empty env vars.","Keep https:// in any custom URL."],"tags":["url","validation","config","himalayas"],"backgroundTag":"invalid-url-format","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}