{"record":{"id":"dd028b5327cb46e7","repo":"santifer/career-ops","slug":"oraclecloud-invalid-url-url","errorCode":null,"errorMessage":"oraclecloud: invalid URL: ${url}","messagePattern":"oraclecloud: invalid URL: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/oraclecloud.mjs","lineNumber":66,"sourceCode":"// oraclecloud99.com. No leading zero, at most two digits — a bounded family,\n// so this stays a host pin and never becomes a wildcard apex match.\nconst ORACLE_HOST_RE = /^[a-z0-9-]+\\.fa\\.(?:[a-z0-9-]+\\.)?(?:ocs\\.)?oraclecloud(?:[1-9][0-9]?)?\\.com$/i;\n\nconst PAGE_SIZE = 200;\nconst MAX_PAGES = 25;             // safety cap (~5000 jobs); hard ceiling like workday\nconst RETRY_POLICY = { retries: 3 };\nconst INTER_PAGE_DELAY_MS = 250;  // WAF-aware spacing between same-host pages\n\n// facetsList is a fixed constant on the finder; %3B is the encoded ';' separator.\nconst FACETS_LIST = 'LOCATIONS%3BWORK_LOCATIONS%3BWORKPLACE_TYPES%3BTITLES%3BCATEGORIES%3BORGANIZATIONS%3BPOSTING_DATES%3BFLEX_FIELDS';\n\n/** @param {string} url */\nfunction assertOracleUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`oraclecloud: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`oraclecloud: URL must use HTTPS: ${url}`);\n  if (!ORACLE_HOST_RE.test(parsed.hostname)) {\n    throw new Error(`oraclecloud: untrusted hostname \"${parsed.hostname}\" — must match *.fa[.<region>][.ocs].oraclecloud[1-99].com`);\n  }\n  return url;\n}\n\n// NaN-safe Date.parse — `|| undefined` would also coerce a valid epoch 0.\n// (copied from greenhouse.mjs)\nfunction toEpochMs(value) {\n  if (!value) return undefined;\n  const parsed = Date.parse(value);\n  return Number.isNaN(parsed) ? undefined : parsed;\n}\n\nfunction sleep(ms, ctx) {\n  if (typeof ctx?.sleep === 'function') return ctx.sleep(ms);","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/santifer/career-ops/blob/e7abd431fce9348a95261acac9e0c14779c35df8/providers/oraclecloud.mjs#L48-L84","documentation":"The oraclecloud provider validates URLs with assertOracleUrl. This error is thrown when the string cannot be parsed by the URL constructor at all — missing scheme, malformed syntax, empty input. It fails before any hostname or protocol checks.","triggerScenarios":"Passing an empty string, a scheme-less host ('mysite.fa.ocs.oraclecloud.com'), or a syntactically broken URL ('https://', 'https:/host') into the oraclecloud provider's detect/fetch path or assertOracleUrl directly.","commonSituations":"Config entry with a missing or truncated Oracle Fusion careers URL; unset env var interpolated into the entry; YAML quoting/line-wrap mistakes; placeholder not replaced in a template entry.","solutions":["Fix the URL so it is a complete absolute https:// URL","Trim whitespace and fix YAML quoting/indentation that may truncate the value","Verify the variable providing the URL is set and non-empty","Remove entries not meant for the Oracle Cloud provider"],"exampleFix":"// before\nconst url = entry.careers_url; // undefined -> 'undefined' string throws\nassertOracleUrl(url);\n// after\nconst url = (entry.careers_url || '').trim();\nif (!url) return null;\nassertOracleUrl(url);","handlingStrategy":"validation","validationCode":"function isParsableUrl(u) { try { new URL(u); return true; } catch { return false; } }\nif (!isParsableUrl(entry.careers_url)) throw new Error(`bad oraclecloud url: ${entry.careers_url}`);","typeGuard":"function isAbsoluteUrl(u) {\n  if (typeof u !== 'string' || !u.trim()) return false;\n  try { const p = new URL(u); return !!p.hostname; } catch { return false; }\n}","tryCatchPattern":"try {\n  useOracle(url);\n} catch (e) {\n  if (String(e.message).startsWith('oraclecloud: invalid URL')) {\n    log.warn(`Skipping malformed Oracle URL: ${url}`);\n    return null;\n  }\n  throw e;\n}","preventionTips":["Parse-validate all provider URLs once at config load","Store full https:// URLs for Oracle Fusion tenants, including the full fa.ocs hostname","Trim and check non-empty every value before passing to the provider","Add a startup dry-run that lists entries failing URL parsing"],"tags":["url-validation","config","input-validation"],"backgroundTag":"invalid-url-format","analyzedSha":"e7abd431fce9348a95261acac9e0c14779c35df8","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}