{"record":{"id":"afbb8898bf94e4bc","repo":"santifer/career-ops","slug":"smartrecruiters-invalid-url-url","errorCode":null,"errorMessage":"smartrecruiters: invalid URL: ${url}","messagePattern":"smartrecruiters: invalid URL: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/smartrecruiters.mjs","lineNumber":70,"sourceCode":" */\nexport function extractDescription(detail) {\n  const sections = detail?.jobAd?.sections;\n  if (!sections || typeof sections !== 'object') return '';\n  const parts = [];\n  for (const key of ['companyDescription', 'jobDescription', 'qualifications', 'additionalInformation']) {\n    const text = sections[key]?.text;\n    if (typeof text === 'string' && text.trim()) parts.push(text);\n  }\n  if (parts.length === 0) return '';\n  return htmlToText(parts.join('\\n'));\n}\n\nfunction assertSmartRecruitersUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`smartrecruiters: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`smartrecruiters: URL must use HTTPS: ${url}`);\n  if (!ALLOWED_SMARTRECRUITERS_HOSTS.has(parsed.hostname)) {\n    throw new Error(`smartrecruiters: untrusted hostname \"${parsed.hostname}\" — must be one of: ${[...ALLOWED_SMARTRECRUITERS_HOSTS].join(', ')}`);\n  }\n  return url;\n}\n\nfunction resolveSlug(entry) {\n  // entry.api takes precedence over careers_url (mirrors greenhouse/ashby) so a\n  // branded page (e.g. https://jobs.continental.com) can stay as careers_url\n  // while the SmartRecruiters slug is pinned via\n  // api: https://careers.smartrecruiters.com/<slug> in portals.yml.\n  for (const raw of [entry.api, entry.careers_url]) {\n    if (typeof raw !== 'string' || !raw) continue;\n    let parsed;\n    try {\n      parsed = new URL(raw);","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/smartrecruiters.mjs#L52-L88","documentation":"assertSmartRecruitersUrl throws this when the URL passed to it cannot be parsed by the URL constructor at all (empty string, missing scheme, spaces, malformed characters). The provider validates every API URL it builds before fetching, so a syntactically invalid URL is rejected immediately rather than producing a confusing fetch error downstream.","triggerScenarios":"Calling fetch with an entry whose derived slug produces a malformed URL, or invoking assertSmartRecruitersUrl directly with user/config-supplied text like 'smartrecruiters.com/v1/...' (missing https://) or an undefined/null coerced to 'undefined'.","commonSituations":"A portals.yml api or careers_url missing the scheme; slug containing characters that break the URL (spaces, control chars); template placeholder left unfilled so the URL reads like a sentence instead of a URL; passing a non-string that stringifies to garbage.","solutions":["Print the offending url in the error and fix its syntax — add the https:// scheme if missing","Ensure entry.api or entry.careers_url is a complete, well-formed URL in portals.yml","Prefer the built-in buildPostingsUrl(slug) helper over hand-assembling API URLs","Trim whitespace and remove invisible characters from configured URLs"],"exampleFix":"// before\nentry.api = 'api.smartrecruiters.com/v1/companies/acme/postings'; // no scheme\n// after\nentry.api = 'https://api.smartrecruiters.com/v1/companies/acme/postings';","handlingStrategy":"validation","validationCode":"function isValidHttpUrl(url) {\n  if (typeof url !== 'string' || !url.trim()) return false;\n  try { new URL(url); return true; } catch { return false; }\n}\nif (!isValidHttpUrl(entry.api)) throw new Error(`bad smartrecruiters api url: ${entry.api}`);","typeGuard":"const isUrl = (v) => {\n  if (typeof v !== 'string') return false;\n  try { new URL(v); return true; } catch { return false; }\n  return true;\n};","tryCatchPattern":"try {\n  await srProvider.fetch(entry, ctx);\n} catch (e) {\n  if (String(e.message).includes('invalid URL')) {\n    console.error(`Entry ${entry.name}: fix the URL syntax in portals.yml — scheme and characters`);\n  } else throw e;\n}","preventionTips":["Always include https:// in configured URLs","Trim whitespace and control characters from config values","Validate all portals entries with a URL constructor pass at load time","Never rely on string concatenation to build URLs — use URL or a builder helper"],"tags":["url-validation","url-parse","config-error"],"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"}