santifer/career-ops · error · Error
itviec: invalid URL
Error message
itviec: invalid URL: ${url} What it means
assertItviecUrl parses a URL and throws this error when new URL() fails, i.e. the string is not an absolute, well-formed URL. The itviec provider runs this check before every request so malformed config can never reach the fetch layer.
Solutions
- Set the URL to a full absolute https URL, e.g. https://www.itviec.com/it-jobs
- Trim/strip surrounding whitespace and quotes from the config value
- Validate all careers_url values in portals.yml are absolute URLs before running scan.mjs
- If the value comes from an env var or CLI arg, check it is defined and well-formed before passing it in
Example fix
// before
assertItviecUrl('itviec.com/it-jobs');
// after
assertItviecUrl('https://www.itviec.com/it-jobs'); Defensive patterns
Strategy: validation
Validate before calling
function isValidAbsoluteUrl(url) {
if (typeof url !== 'string') return false;
try { new URL(url.trim()); return true; } catch { return false; }
}
// pre-validate config: if (!isValidAbsoluteUrl(entry.careers_url)) skip; Type guard
const isUrl = (v) => { try { return typeof v === 'string' && !!new URL(v); } catch { return false; } }; Try / catch
try {
assertItviecUrl(url);
} catch (err) {
if (/invalid URL/.test(err.message)) {
console.warn(`itviec entry has malformed URL, skipping: ${url}`);
return null;
}
throw err;
} Prevention
- Always store full absolute URLs with scheme in config files
- Trim whitespace/quotes when reading YAML string values
- Validate portals.yml at load time, before any fetch
- Watch for unsubstituted template placeholders in config
When it happens
Trigger: new URL(url) throws for the given string — relative path like '/it-jobs', missing scheme ('itviec.com/it-jobs'), stray whitespace, or a non-string coerced to garbage — and it is passed to assertItviecUrl.
Common situations: portals.yml careers_url written without https://; a template placeholder left unsubstituted; the entry stores a path instead of a full URL; trailing spaces/quotes around the value in YAML.
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
- apify: entry has invalid field_map. Each of title, url…
- apify: entry missing 'actor' (e.g. misceres/indeed-scraper)
- arbeitnow: invalid URL
- ashby: invalid URL
- bamboohr: invalid URL
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/cd2da10f94172377.
Report an issue: GitHub.
Appendix: source
Thrown at providers/itviec.mjs:82
const LOCATION_RE = /#map-pin"?><\/use><\/svg>\s*<div[^>]*title=["']([^"']*)["']/i;
/** Relative publication label: English "Posted … ago" or Vietnamese "Đăng … trước". */
const POSTED_LABEL_RE =
/(?:Posted|Đăng)\s*:?\s*(?:<\/\w+>\s*)?([^.<]{0,40}?(?:ago|trước)|today|hôm nay)/i;
/** @param {any} ctx @param {number} ms */
function sleep(ctx, ms) {
if (typeof ctx?.sleep === 'function') return ctx.sleep(ms);
return new Promise((r) => setTimeout(r, ms));
}
/** @param {string} url */
function assertItviecUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`itviec: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`itviec: URL must use HTTPS: ${url}`);
if (parsed.hostname !== TRUSTED_HOST) {
throw new Error(`itviec: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_HOST}`);
}
return url;
}
/**
* Collapse a markup fragment to its visible text.
* @param {string} fragment
* @returns {string}
*/
export function visibleText(fragment) {
return decodeEntities(
String(fragment ?? '')
.replace(/<!--[\s\S]*?-->/g, ' ')
.replace(/<[^>]+>/g, ' '),View on GitHub (pinned to aac998c7ed)