multica-ai/multica · error
--batch-size must be positive
Error message
--batch-size must be positive
What it means
Config validation error: --batch-size was supplied as zero or negative (or its default left uninitialized in a non-flag context). The batch size controls how many task_usage rows each UPDATE round touches, so the tool requires a positive value before proceeding.
Source
Thrown at server/cmd/backfill_codex_usage_cache/main.go:172
"to", rollupTo.Format(time.RFC3339),
"rows_touched", rollupRows)
return nil
}
func (cfg *config) parseAndValidate(now time.Time) error {
if cfg.cutoffRaw == "" {
return fmt.Errorf("--cutoff is required; use the hosted deployment time of the Codex usage normalization fix")
}
cutoff, err := time.Parse(time.RFC3339, cfg.cutoffRaw)
if err != nil {
return fmt.Errorf("parse --cutoff as RFC3339: %w", err)
}
cutoff = cutoff.UTC()
if !cutoff.Before(now) {
return fmt.Errorf("--cutoff must be before now; refusing a future cutoff because it could double-subtract already-normalized rows")
}
if cfg.batchSize <= 0 {
return fmt.Errorf("--batch-size must be positive")
}
cfg.cutoff = cutoff
return nil
}
func loadDryRunSummary(ctx context.Context, pool *pgxpool.Pool, cfg config) ([]summaryRow, totals, error) {
const query = `
SELECT
a.workspace_id::text AS workspace_id,
(tu.created_at AT TIME ZONE 'UTC')::date::text AS date_utc,
COUNT(*)::bigint AS rows,
COALESCE(SUM(tu.input_tokens), 0)::bigint AS input_before,
COALESCE(SUM(GREATEST(tu.input_tokens - tu.cache_read_tokens, 0)), 0)::bigint AS input_after,
COALESCE(SUM(tu.input_tokens - GREATEST(tu.input_tokens - tu.cache_read_tokens, 0)), 0)::bigint AS overcount,
COUNT(*) FILTER (WHERE tu.input_tokens < tu.cache_read_tokens)::bigint AS clamped_rows,
MIN(tu.created_at) AS min_created_at,
MAX(tu.created_at) AS max_created_at
FROM task_usage tuView on GitHub (pinned to 2c0912b6ec)
Solutions
- Pass a positive integer, e.g. --batch-size 5000.
- Default the variable in the script: BATCH=${BATCH:-5000} before invoking.
- Tune the value against database load; there is no need for extreme sizes since the tool loops until done.
Example fix
# before
BATCH=
./backfill_codex_usage_cache --cutoff ... --batch-size $BATCH
# --batch-size must be positive
# after
BATCH=${BATCH:-5000}
./backfill_codex_usage_cache --cutoff 2026-06-01T12:00:00Z --batch-size $BATCH --execute Defensive patterns
Strategy: validation
Validate before calling
BATCH=${BATCH:-5000}
case "$BATCH" in (*[!0-9]*|'') echo '--batch-size must be a positive integer'; exit 1;; esac
./backfill_codex_usage_cache --cutoff "$CUTOFF" --batch-size "$BATCH" Prevention
- Default batch variables in runbooks so unset env vars never reach the flag.
- Pick moderate sizes (e.g. 1000–10000) — the tool loops to completion on its own.
When it happens
Trigger: Passing --batch-size 0 or a negative number; an wrapper script passing an unset shell variable that expands to nothing/0.
Common situations: Parameterized runbooks interpolating an empty variable (--batch-size $BATCH with BATCH unset); attempting 'unbatched' mode with 0; typo'd negative value.
Related errors
- --cutoff is required; use the hosted deployment time of the
- parse --cutoff as RFC3339: %w
- --cutoff must be before now; refusing a future cutoff becaus
- --%s, --%s-stdin, and --%s-file are mutually exclusive; pick
- --%s-file: path must not be empty
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/933c01631ab2e75d.
Report an issue: GitHub.