{"record":{"id":"a4d65e687ebfa624","repo":"abhigyanpatwari/GitNexus","slug":"malformed-shard-arg-malformed-expected","errorCode":null,"errorMessage":"Malformed --shard arg '${malformed}' — expected --shard=<index>/<total>","messagePattern":"Malformed --shard arg '(.+?)' — expected --shard=<index>/<total>","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/scripts/shard-arg.ts","lineNumber":27,"sourceCode":" */\n\nconst SHARD_RE = /^--shard=\\d+\\/\\d+$/;\n\n/**\n * Returns the matched `--shard=<index>/<total>` token (e.g. `--shard=1/3`) to\n * pass straight through to vitest, or `undefined` when no shard arg is present.\n *\n * Fails loud on a shard-shaped-but-malformed arg (e.g. `--shard=1`, `--shard`,\n * `--shard=abc`): a silently-ignored malformed arg would drop the shard flag and\n * run the full unsharded ~50-spawn suite, re-arming the Windows watchdog timeout\n * with no signal. Only `--shard` / `--shard=…` args are inspected, so unrelated\n * flags (including a hypothetical `--shardx=…`) pass through untouched.\n */\nexport function parseShardArg(argv: string[]): string | undefined {\n  const shardArgs = argv.filter((a) => a === '--shard' || a.startsWith('--shard='));\n  const malformed = shardArgs.find((a) => !SHARD_RE.test(a));\n  if (malformed !== undefined) {\n    throw new Error(`Malformed --shard arg '${malformed}' — expected --shard=<index>/<total>`);\n  }\n  return shardArgs[0];\n}\n","sourceCodeStart":9,"sourceCodeEnd":31,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/scripts/shard-arg.ts#L9-L31","documentation":"Thrown by parseShardArg() when an argv token begins with '--shard' but does not match the exact shape --shard=<digits>/<digits>. The function deliberately fails loud because a silently-dropped malformed shard flag would fall back to running the full unsharded suite (~50 spawns), re-arming the Windows watchdog timeout with no visible signal.","triggerScenarios":"Invoking the cross-platform script with '--shard=1' (missing /total), '--shard' alone (no value), '--shard=abc' (non-numeric), '--shard=1/' or '--shard=/3' (missing half), or '--shard=1.0/3' (float).","commonSituations":"A CI workflow that interpolates SHARD_INDEX and SHARD_TOTAL as separate vars but forgets one, producing '--shard=2/'; a typo passing '--shard 1/3' as two tokens (the bare '--shard' is malformed); copy-pasting vitest's '--shard=1/3' syntax but with a non-integer.","solutions":["Use the exact form: --shard=<index>/<total>, e.g. --shard=1/3.","When interpolating env vars, guard both: --shard=${INDEX}/${TOTAL} with both required and integer-validated upstream.","Pass --shard as a single =-joined token; do not split it into two argv entries."],"exampleFix":"# before\nnode scripts/run-cross-platform.js --shard \"$INDEX\"/\"$TOTAL\"\n# (produces a bare '--shard' plus a separate token if INDEX is empty)\n\n# after\nnode scripts/run-cross-platform.js \"--shard=${INDEX}/${TOTAL}\"","handlingStrategy":"validation","validationCode":"const SHARD_RE = /^--shard=(\\d+)\\/(\\d+)$/;\nfunction buildShardFlag(index, total) {\n  const i = Math.floor(Number(index));\n  const t = Math.floor(Number(total));\n  if (!Number.isInteger(i) || !Number.isInteger(t) || i < 1 || t < 1 || i > t) {\n    throw new Error(`cannot build shard flag from index=${index}, total=${total}`);\n  }\n  return `--shard=${i}/${t}`;\n}","typeGuard":"function isWellFormedShardArg(arg: string): boolean {\n  return /^--shard=\\d+\\/\\d+$/.test(arg);\n}","tryCatchPattern":null,"preventionTips":["Always pass --shard as a single =-joined argv token, never as two.","When interpolating env vars, require both INDEX and TOTAL before constructing the flag.","Add a CI step that asserts the shard flag matches /^--shard=\\d+\\/\\d+$/ before the script runs."],"tags":["cli","validation","sharding","ci"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}