vitest-dev/vitest · error · Error

--shard <count> must be a positive number

Error message

--shard <count> must be a positive number

What it means

The --shard flag takes the form `<index>/<count>`. This error fires when the count portion is missing, non-numeric, or zero. The check at resolveConfig.ts:331 parses the count via Number.parseInt and rejects NaN or values <= 0, because a shard count of 0 makes the index meaningless.

Source

Thrown at packages/vitest/src/node/config/resolveConfig.ts:332

  }

  if (viteConfig.base !== '/') {
    resolved.base = viteConfig.base
  }

  resolved.clearScreen = resolved.clearScreen ?? viteConfig.clearScreen ?? true

  if (options.shard) {
    if (resolved.watch) {
      throw new Error('You cannot use --shard option with enabled watch')
    }

    const [indexString, countString] = options.shard.split('/')
    const index = Math.abs(Number.parseInt(indexString, 10))
    const count = Math.abs(Number.parseInt(countString, 10))

    if (Number.isNaN(count) || count <= 0) {
      throw new Error('--shard <count> must be a positive number')
    }

    if (Number.isNaN(index) || index <= 0 || index > count) {
      throw new Error(
        '--shard <index> must be a positive number less then <count>',
      )
    }

    resolved.shard = { index, count }
  }

  if (resolved.standalone && !resolved.watch) {
    throw new Error(`Vitest standalone mode requires --watch`)
  }

  if (resolved.mergeReports && resolved.watch) {
    throw new Error(`Cannot merge reports with --watch enabled`)
  }

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Pass both index and count as positive integers: `--shard 1/4`.
  2. If the count comes from a CI variable, verify it is set and numeric before invoking vitest.
  3. Quote the value in shell to avoid glob/word-splitting: `--shard "${INDEX}/${TOTAL}"`.

Example fix

# before
vitest --shard 1/0
# after
vitest --shard 1/4
Defensive patterns

Strategy: validation

Validate before calling

function parseShard(raw: string): { index: number; count: number } {
  const [i, c] = raw.split('/')
  const count = Number.parseInt(c, 10)
  if (Number.isNaN(count) || count <= 0) throw new Error(`Invalid shard count: ${raw}`)
  const index = Number.parseInt(i, 10)
  if (Number.isNaN(index) || index <= 0 || index > count) throw new Error(`Invalid shard index: ${raw}`)
  return { index, count }
}

Type guard

function isValidShard(raw: string): boolean {
  const [i, c] = raw.split('/')
  const count = Number.parseInt(c, 10)
  const index = Number.parseInt(i, 10)
  return !Number.isNaN(count) && count > 0 && !Number.isNaN(index) && index > 0 && index <= count
}

Prevention

When it happens

Trigger: Run `vitest --shard 1/0`, `vitest --shard 2/abc`, or `vitest --shard 3` (missing the slash and count).

Common situations: Typo in a CI matrix script; dynamic shard count from a variable that evaluated to empty/0; misreading the shard format as a single number.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/64c2f3383b41ba14.json. Report an issue: GitHub.