santifer/career-ops · error · Error
local-parser: company name cannot start with
Error message
local-parser: company name cannot start with '-': ${value} What it means
safeCompany() validates the {company} placeholder before argv interpolation. Because execFile passes args verbatim (no shell), the only injection risk is a value that looks like a CLI flag; a company name starting with '-' would be read as an option by the parser process, so it is rejected.
Solutions
- Rename the entry in portals.yml so name does not begin with '-', or strip the leading character.
- Quote the YAML value properly so a leading dash is part of the intended name only if you also change it (this validator will still reject it — reword instead).
- Move the flag-like token out of the company name, e.g. 'Acme-404' instead of '-404 Acme'.
- If the parser genuinely needs a flag-like value, pass it via a dedicated non-interpolated parser arg, not via {company}.
Example fix
// before (portals.yml)
- name: "-404 Studio"
parser: {command: node, args: ["parsers/jobs.js", "{company}"]}
// after
- name: "Studio 404"
parser: {command: node, args: ["parsers/jobs.js", "{company}"]} Defensive patterns
Strategy: validation
Validate before calling
const name = String(entry.name || '').trim();
if (name.startsWith('-')) throw new Error(`${entry.name}: company name must not start with '-' (would be read as a CLI flag)`); Try / catch
try {
await localParser.fetch(entry);
} catch (e) {
if (String(e.message).includes("cannot start with '-'")) {
console.error(`Rename ${entry.name}: leading '-' looks like a CLI flag to the parser process`);
return [];
}
throw e;
} Prevention
- Sanitize company names when generating portals.yml programmatically (trim, strip leading dashes).
- Quote YAML values, but reword rather than keep leading punctuation.
- Avoid using slugs or negative-number-like tokens as entry names.
- Review copy-pasted entries for stray bullet/dash characters.
When it happens
Trigger: A portals.yml entry whose parser args contain `{company}` and whose entry.name (after trim) starts with '-', e.g. name: ' - Acme' or a name like '-404 Studio'.
Common situations: Leading dash/hyphen from copy-paste artifacts (bullets, dashes); negative-number-like slugs used as company identifiers; YAML values that accidentally begin with '-' due to quoting mistakes.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- a 40-hex commit --sha is required
- arbeitnow: URL must use HTTPS
- eightfold: URL must use HTTPS
- justjoin: untrusted hostname
- local-parser: careers_url must be http(s)
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/1b64dc73f83d1914.
Report an issue: GitHub.
Appendix: source
Thrown at providers/local-parser.mjs:43
let url;
try {
url = new URL(String(value));
} catch {
throw new Error(`local-parser: careers_url is not a valid URL: ${value}`);
}
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
throw new Error(`local-parser: careers_url must be http(s): ${value}`);
}
return url.href;
}
function safeCompany(value) {
if (!value) return '';
const name = String(value).trim();
// execFile passes args verbatim (no shell), so the only injection risk is a
// value that begins like a CLI flag.
if (name.startsWith('-')) {
throw new Error(`local-parser: company name cannot start with '-': ${value}`);
}
return name;
}
// Only validate a placeholder's value when the arg actually uses it — a fixed
// `parser.script` must not be rejected because some unrelated `{company}` value
// has punctuation it never sees.
function expandParserArg(value, entry) {
let out = String(value);
if (out.includes('{careers_url}')) out = out.replaceAll('{careers_url}', safeCareersUrl(entry.careers_url));
if (out.includes('{company}')) out = out.replaceAll('{company}', safeCompany(entry.name));
return out;
}
function getParserScriptPath(entry) {
const parser = entry.parser || {};
if (parser.script) return expandParserArg(parser.script, entry);
View on GitHub (pinned to aac998c7ed)