{"record":{"id":"3c9ffa054bbed6f9","repo":"stablyai/orca","slug":"higher-is-better-requires-a-metric-key","errorCode":null,"errorMessage":"--higher-is-better requires a metric key","messagePattern":"--higher-is-better requires a metric key","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/compare-benchmark-artifacts.mjs","lineNumber":48,"sourceCode":"      continue\n    }\n    if (flag === '--output') {\n      parsed.outputPath = readRequiredValue(args, ++index, '--output requires a path')\n      continue\n    }\n    if (flag === '--json-output') {\n      parsed.jsonOutputPath = readRequiredValue(args, ++index, '--json-output requires a path')\n      continue\n    }\n    if (flag === '--higher-is-better') {\n      let consumed = 0\n      while (args[index + 1] != null && !args[index + 1].startsWith('--')) {\n        parsed.higherIsBetter.add(args[index + 1])\n        index += 1\n        consumed += 1\n      }\n      if (consumed === 0) {\n        throw new Error('--higher-is-better requires a metric key')\n      }\n      continue\n    }\n    throw new Error(USAGE)\n  }\n\n  if (!parsed.baselinePath) {\n    throw new Error(USAGE)\n  }\n  if (!parsed.candidatePath) {\n    throw new Error(USAGE)\n  }\n  return parsed\n}\n\nfunction readRequiredValue(args, index, message) {\n  const value = args[index]\n  if (value == null || value.startsWith('--')) {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/compare-benchmark-artifacts.mjs#L30-L66","documentation":"Thrown by parseBenchmarkComparisonArgs when the --higher-is-better flag is followed by zero non-flag arguments. The flag greedily consumes subsequent args until it hits another --flag or end of args; if nothing follows, the metric-key set is empty and the flag had no effect, which the parser rejects rather than silently defaulting to all-lower-is-better.","triggerScenarios":"Invoking compare-benchmark-artifacts.mjs --baseline a.json --candidate b.json --higher-is-better (no key after the flag); the key was itself a flag-like token starting with '--'; the flag was placed at the very end of the command line.","commonSituations":"Operator forgets the metric key; CI workflow templated the flag with an empty value; the metric key was meant to be passed via a variable that expanded to empty.","solutions":["Pass at least one metric key after the flag: --higher-is-better opsPerSec throughput.","If the metric key legitimately starts with '--', restructure (this parser treats any next arg starting with '--' as a new flag).","Remove the --higher-is-better flag entirely if all metrics are lower-is-better (the default).","In CI, guard the workflow so the flag is only emitted when the metric-key variable is non-empty."],"exampleFix":"// before\n// node config/scripts/compare-benchmark-artifacts.mjs --baseline a.json --candidate b.json --higher-is-better\n// -> '--higher-is-better requires a metric key'\n\n// after\n// node config/scripts/compare-benchmark-artifacts.mjs --baseline a.json --candidate b.json --higher-is-better throughput","handlingStrategy":"validation","validationCode":"function parseHigherIsBetter(args, index) {\n  const keys = []\n  while (args[index + 1] != null && !args[index + 1].startsWith('--')) {\n    keys.push(args[index + 1])\n    index += 1\n  }\n  if (keys.length === 0) {\n    throw new Error('--higher-is-better requires a metric key')\n  }\n  return { keys, nextIndex: index }\n}\n// use from parseBenchmarkComparisonArgs","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass at least one metric key after --higher-is-better.","In CI, only emit the flag when the metric-key variable is non-empty: ${KEY:+--higher-is-better $KEY}.","Remember the parser treats any next arg starting with '--' as a new flag — do not name metrics with a leading dash."],"tags":["cli","arg-parsing","benchmark","validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}