santifer/career-ops · error · Error
jobstreet: invalid URL: ${url}
Error message
jobstreet: invalid URL: ${url} What it means
Thrown by assertJobstreetUrl when new URL(url) throws — the supplied api URL is not a parseable absolute URL. Unlike the himalayas/jobspresso guards, the jobstreet assert runs against entry.api || DEFAULT_API, so it IS reachable from the public contract whenever entry.api is set to a malformed string.
Source
Thrown at providers/jobstreet.mjs:56
'jobstreet.co.id',
'sg.jobstreet.com',
'my.jobstreet.com',
'www.seek.com.au',
'www.seek.co.nz',
]);
// v5 API paths (the client-side JS on jobstreet uses these relative paths
// resolved against the current origin). We keep the allowlist for SSRF
// protection on the base URL, then build the v5 search path from it.
const V5_SEARCH_PATH = '/api/jobsearch/v5/search';
/** @param {string} url */
function assertJobstreetUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`jobstreet: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`jobstreet: URL must use HTTPS: ${url}`);
if (!ALLOWED_JOBSTREET_HOSTS.has(parsed.hostname))
throw new Error(`jobstreet: untrusted hostname "${parsed.hostname}" — must be one of: ${[...ALLOWED_JOBSTREET_HOSTS].join(', ')}`);
return url;
}
/**
* Derive the origin from the API hostname.
* e.g. id.jobstreet.com → https://id.jobstreet.com
* @param {string} apiUrl
* @returns {string}
*/
function deriveOrigin(apiUrl) {
try {
const parsed = new URL(apiUrl);
return `${parsed.protocol}//${parsed.hostname}`;
} catch {View on GitHub (pinned to 9b17a8ac97)
Solutions
- Set api: to a full absolute URL including the https:// scheme, e.g. https://id.jobstreet.com/api/jobsearch/v5/search.
- If you do not need a custom endpoint, remove api: and let the provider use DEFAULT_API.
- Trim whitespace and confirm new URL(entry.api) does not throw before running the scan.
Example fix
# before - name: Jobstreet ID provider: jobstreet api: id.jobstreet.com/api/jobsearch/v5/search # after - name: Jobstreet ID provider: jobstreet api: https://id.jobstreet.com/api/jobsearch/v5/search
Defensive patterns
Strategy: validation
Validate before calling
// Validate a user-supplied entry.api before the provider's assert throws.
if (typeof entry.api === 'string') {
try { new URL(entry.api); }
catch { throw new Error(`jobstreet: entry.api is not a valid absolute URL: ${entry.api}`); }
} Type guard
/** True for a parseable absolute URL string. */
function isAbsoluteUrl(value) {
if (typeof value !== 'string' || !value.trim()) return false;
try { new URL(value); return true; } catch { return false; }
} Try / catch
try {
return await jobstreetProvider.fetch(entry, ctx);
} catch (err) {
if (/jobstreet: invalid URL/.test(err.message)) {
console.error(`config: ${entry.name} — entry.api is malformed: ${err.message}`);
} else {
throw err;
}
} Prevention
- Always include the https:// scheme when setting entry.api; omit api: to use the well-formed default.
- Trim whitespace from YAML values; quote URLs containing special characters.
- Lint all provider: jobstreet entries for a parseable api: before a scan.
When it happens
Trigger: A portal entry with provider: jobstreet and api: set to a malformed string — missing scheme (e.g. 'id.jobstreet.com/api/jobsearch/v5/search'), stray whitespace/characters, or a relative path. When entry.api is absent the provider uses the well-formed DEFAULT_API and this never fires.
Common situations: Omitting the https:// scheme when setting api:; a copy-paste that included surrounding quotes or whitespace; a templating step that produced a relative URL; YAML treating a value with special characters oddly.
Related errors
- jobstreet: URL must use HTTPS: ${url}
- jobstreet: untrusted hostname "${parsed.hostname}" — must be
- arbeitnow: invalid URL: ${url}
- ashby: invalid URL: ${url}
- bamboohr: invalid URL: ${url}
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/bf6bdebc2c61dd9f.
Report an issue: GitHub.