santifer/career-ops · error · Error

local-parser: the parser script must be the interpreter's fi

Error message

local-parser: the parser script must be the interpreter's first argument

What it means

For a whitelisted interpreter, the parser script must be args[0] — the interpreter's first argument. If anything precedes the script (an interpreter option like --eval, --require, -c, --inspect), this error fires. The rule blocks interpreter options that could execute arbitrary code (node --eval '...', python -c '...').

Source

Thrown at providers/local-parser.mjs:114

  return resolveInsideRoot(value);
}

// Validate the whole invocation and return what to spawn. Throws on anything unsafe.
function resolveInvocation(entry) {
  const rawCommand = String(entry.parser?.command || '');
  const command = resolveCommand(rawCommand);
  const args = buildParserArgs(entry);
  const scriptPath = getParserScriptPath(entry);

  const usesInterpreter = !rawCommand.includes('/') && ALLOWED_INTERPRETERS.has(rawCommand);
  if (usesInterpreter) {
    // A whitelisted interpreter must run an in-repo script as its FIRST argument.
    // Anything before the script is an interpreter option (node --eval / --require,
    // python -c, …) that could execute arbitrary code, so require the script to lead.
    if (!scriptPath) throw new Error('local-parser: interpreter command requires an in-repo parser script');
    resolveInsideRoot(scriptPath);
    if (args[0] !== scriptPath) {
      throw new Error('local-parser: the parser script must be the interpreter\'s first argument');
    }
  } else if (scriptPath) {
    // command is an in-repo file; keep any detected script path inside the repo too.
    resolveInsideRoot(scriptPath);
  }

  return { command, args };
}

function normalizeJobUrl(rawUrl, baseUrl) {
  if (!rawUrl) return '';
  try {
    return new URL(String(rawUrl).trim(), baseUrl || undefined).href;
  } catch {
    return '';
  }
}

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Reorder parser.args so the script path is first: args: ['parsers/acme.py', '--require','./hook.js'] (note: options after the script are passed to the script, not the interpreter — adjust accordingly).
  2. If you need interpreter options, do not use local-parser's argv expansion; wrap the invocation in an in-repo shell script instead.
  3. Remove any leading --eval/-c style options.

Example fix

# before
parser:
  command: node
  script: parsers/acme.js
  args: ['--require', './hook.js', 'parsers/acme.js']

# after (hook logic moved inside the parser script)
parser:
  command: node
  script: parsers/acme.js
  args: ['parsers/acme.js', '{careers_url}']
Defensive patterns

Strategy: validation

Validate before calling

const INTERPRETERS = new Set(['python3','python','node','deno','bun','sh','bash']);
export function scriptIsFirstArg(entry) {
  const cmd = String(entry?.parser?.command || '');
  if (!INTERPRETERS.has(cmd)) return true;
  const script = entry?.parser?.script;
  const args = Array.isArray(entry?.parser?.args) ? entry.parser.args : [];
  return !script || args[0] === script;
}

Type guard

const INTERPRETERS = new Set(['python3','python','node','deno','bun','sh','bash']);
/** @param {any} entry */
function argsLeadWithScript(entry) {
  const cmd = String(entry?.parser?.command || '');
  if (!INTERPRETERS.has(cmd)) return true;
  const script = entry?.parser?.script;
  const args = Array.isArray(entry?.parser?.args) ? entry.parser.args : [];
  return !script || args[0] === script;
}

Try / catch

try {
  await provider.fetch(entry, ctx);
} catch (err) {
  if (err.message.includes("first argument")) console.warn(`reorder parser.args so the script leads for ${entry.name}`);
  throw err;
}

Prevention

When it happens

Trigger: parser.args lists an option before the script, e.g. args: ['--require','./hook.js','parsers/acme.py'], or the script is not the first element. args[0] !== scriptPath triggers the throw.

Common situations: A developer tried to inject a --require hook or environment setup before the script; args ordering was changed; the script was placed later in the array by mistake.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/b1e5e743d5b35389. Report an issue: GitHub.