santifer/career-ops · error · Error

yourator: invalid URL: ${url}

Error message

yourator: invalid URL: ${url}

What it means

Thrown by assertYouratorUrl() in providers/yourator.mjs when the URL given for a Yourator endpoint cannot be parsed by new URL(). Like its wttj counterpart, the Yourator provider pins all requests to a trusted https host and fails fast on unparseable input before making any request.

Source

Thrown at providers/yourator.mjs:81

// Per the Job contract, postedAt is omitted rather than guessed — a synthesized
// date would silently corrupt scan-ats-full.mjs's recency filtering.

const SITE_ORIGIN = 'https://www.yourator.co';
const FEED_BASE = `${SITE_ORIGIN}/api/v4/jobs`;
const TRUSTED_HOST = 'www.yourator.co';
// Safety bound only — the loop stops on payload.hasMore. The live board was 88
// pages on 2026-08-18; this leaves room to grow without silently truncating.
const DEFAULT_MAX_PAGES = 120;
const MAX_PAGES_CAP = 500;
const PAGE_DELAY_MS = 200;

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

/** Resolve the page cap: a positive integer `max_pages` on the entry, capped. */
function resolveMaxPages(entry) {
  const v = entry?.max_pages;
  if (Number.isInteger(v) && v > 0) return Math.min(v, MAX_PAGES_CAP);
  return DEFAULT_MAX_PAGES;
}

/**
 * Canonical URL for a posting — Source Indexing Policy rule 2, "the shortest
 * verifiable path to the employer the source exposes".

View on GitHub (pinned to 1696bec4d0)

Solutions

  1. Look at the literal url in the message to spot empty/undefined/scheme-less input.
  2. Prefix the value with 'https://' if only the scheme is missing.
  3. Fix the upstream config value (portals.yml entry or env var) so a full URL reaches the provider.
  4. Pre-validate with new URL(url) at the config-load site to surface the problem earlier.

Example fix

// before
const url = 'yourator.co/api/v3/jobs';
assertYouratorUrl(url);
// after
const url = 'https://yourator.co/api/v3/jobs';
assertYouratorUrl(url);
Defensive patterns

Strategy: validation

Validate before calling

function isParseableYouratorUrl(u) { try { return new URL(u).protocol === 'https:'; } catch { return false; } }
if (!isParseableYouratorUrl(entry.yourator.baseUrl)) throw new Error(`yourator: bad baseUrl ${entry.yourator.baseUrl}`);

Type guard

function toYouratorUrl(v) {
  try { const u = new URL(v); return u.protocol === 'https:' && u.hostname === 'yourator.co' ? u : null; } catch { return null; }
}

Try / catch

try {
  await youratorProvider.fetch(entry);
} catch (e) {
  if (e.message.startsWith('yourator: invalid URL')) {
    console.warn(`Yourator entry misconfigured: ${e.message}`);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the yourator provider with an empty, scheme-less (e.g. 'yourator.co/xxx'), whitespace-containing, or interpolated-undefined URL string so that URL construction throws.

Common situations: Company slug or base URL configured without a scheme in portals.yml, an env var left unset producing an empty/undefined URL, or a string-concatenation bug joining path parts incorrectly.

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


AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01). Data as JSON: /api/errors/0ba1779792a4f849. Report an issue: GitHub.