multica-ai/multica · error

--cutoff must be before now; refusing a future cutoff becaus

Error message

--cutoff must be before now; refusing a future cutoff because it could double-subtract already-normalized rows

What it means

Config validation guard: the parsed --cutoff is not strictly before the current time, and the tool refuses future cutoffs. Rationale: rows with updated_at/created_at after the cutoff are assumed already normalized by the fixed code; a future cutoff would make the correction re-subtract cache_read_tokens from rows that were already normalized, double-counting.

Source

Thrown at server/cmd/backfill_codex_usage_cache/main.go:169

	}
	slog.Info("hourly rollup rebuilt",
		"from", rollupFrom.Format(time.RFC3339),
		"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,

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Set --cutoff to the actual hosted deployment time of the Codex usage normalization fix — always in the past.
  2. If you really meant 'everything', use a safely past timestamp (e.g. the fix deployment moment), not now.
  3. Double-check the year/timezone in the timestamp; note the value is converted to UTC before comparison.

Example fix

# before
./backfill_codex_usage_cache --cutoff 2027-01-01T00:00:00Z  # wrong year → future
# --cutoff must be before now; ...

# after
./backfill_codex_usage_cache --cutoff 2026-06-01T12:00:00Z
Defensive patterns

Strategy: validation

Validate before calling

# Refuse future cutoffs in the wrapper
now=$(date -u +%s); c=$(date -u -d "$CUTOFF" +%s)
[ "$c" -lt "$now" ] || { echo 'cutoff must be in the past'; exit 1; }

Prevention

When it happens

Trigger: Passing a cutoff at or after the current clock time (now), including a cutoff exactly equal to now; also clock skew if the operator's machine is behind the intended cutoff timezone-wise after UTC conversion.

Common situations: Picking 'now' or tomorrow as a backstop; copy-pasting a deployment date from the future by typo (wrong year); generating the cutoff from a script that emits a wrong (future) date.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/9c9e17c4daf739b9. Report an issue: GitHub.