abhigyanpatwari/GitNexus · error · Error
shard index must be in 1..${total}, got ${index}
Error message
shard index must be in 1..${total}, got ${index} What it means
Thrown by shardFiles() when the 1-based 'index' (which shard to select) is not an integer, is less than 1, or exceeds 'total'. The function is called independently on each CI runner, so every runner must agree on the same (index, total) pair to produce a covering, non-overlapping partition.
Source
Thrown at gitnexus/scripts/cross-platform-shard.ts:116
* than enough here, where the goal is only "no shard gets two monsters".
*
* Ties break on the file path so the partition is DETERMINISTIC: every shard
* computes the same split independently, on a different machine, with no
* coordination — which is what lets each runner select its own slice.
*
* Returns files in the input list's original order, not weight order, so failure
* output and reruns stay readable.
*/
export function shardFiles(
files: readonly string[],
index: number,
total: number,
): readonly string[] {
if (!Number.isInteger(total) || total < 1) {
throw new Error(`shard total must be a positive integer, got ${total}`);
}
if (!Number.isInteger(index) || index < 1 || index > total) {
throw new Error(`shard index must be in 1..${total}, got ${index}`);
}
if (total === 1) return [...files];
const byWeightDesc = [...files].sort((a, b) => {
const diff = weightOf(b) - weightOf(a);
return diff !== 0 ? diff : a.localeCompare(b);
});
const loads = Array.from({ length: total }, () => 0);
const assigned = Array.from({ length: total }, () => new Set<string>());
for (const file of byWeightDesc) {
let lightest = 0;
for (let i = 1; i < total; i++) {
if (loads[i]! < loads[lightest]!) lightest = i;
}
assigned[lightest]!.add(file);
loads[lightest]! += weightOf(file);
}View on GitHub (pinned to d540b00184)
Solutions
- Ensure index is 1-based and within [1, total]: if your source is zero-based, pass index0 + 1.
- Validate the pair together: if (!(index >= 1 && index <= total)) throw a clearer upstream error.
- Coerce from env: Math.min(total, Math.max(1, Math.floor(Number(process.env.SHARD_INDEX) || 1))).
Example fix
// before (zero-based matrix variable i) const mine = shardFiles(files, i, total); // after const mine = shardFiles(files, i + 1, total);
Defensive patterns
Strategy: validation
Validate before calling
function safeIndex(index, total) {
const i = Math.floor(Number(index));
if (!Number.isInteger(i) || i < 1 || i > total) {
throw new Error(`shard index ${index} out of range 1..${total}`);
}
return i;
} Type guard
function isValidShardIndex(index: unknown, total: number): index is number {
return typeof index === 'number' && Number.isInteger(index) && index >= 1 && index <= total;
} Prevention
- Remember shardFiles uses 1-based indexing; convert zero-based matrix vars with +1.
- Validate index against total in the same function that parses the shard flag.
- Log the resolved (index, total) pair at the start of the runner for quick diagnosis.
When it happens
Trigger: Calling shardFiles(files, 0, 3) (zero-based index mistake), shardFiles(files, 4, 3) (index exceeds total), shardFiles(files, 1.5, 3), or shardFiles(files, NaN, 3).
Common situations: Treating the shard index as zero-based when the API expects 1-based (the most common cause); a CI matrix that numbers shards 1..N but a job variable offset by one; reading the index from an env var that was never validated.
Related errors
- shard total must be a positive integer, got ${total}
- Malformed --shard arg '${malformed}' — expected --shard=<ind
- [understand-quickly] expected id of the form "owner/repo", g
- Unsupported provider: ${(config as any).provider}
- Invalid backend URL: must be a well-formed http:// or https:
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/8b028bc8ba66514e.
Report an issue: GitHub.