JuliusBrussee/caveman · error

experiment label must be 1-128 bytes

Error message

experiment label must be 1-128 bytes

What it means

StartExperiment validated the experiment label and found it empty or longer than 128 bytes. The label bounds keep experiment metadata queryable and bounded before any experiment state is created.

Source

Thrown at proxy/internal/store/learn_experiment.go:90

type ExperimentReport struct {
	Schema     string                `json:"schema"`
	Basis      string                `json:"basis"`
	Label      string                `json:"label"`
	SinkID     string                `json:"sink_id,omitempty"`
	FixKind    string                `json:"fix_kind,omitempty"`
	Arms       []ExperimentArmResult `json:"arms"`
	Verdict    string                `json:"verdict"`
	DeltaPct   *float64              `json:"median_session_tokens_delta_pct,omitempty"`
	SavedUSD   *float64              `json:"saved_usd_per_session,omitempty"`
	Currency   string                `json:"currency,omitempty"`
	Attributed LearnAttribution      `json:"attribution"`
	Caveats    []string              `json:"caveats"`
}

func (s *Store) StartExperiment(label, sinkID, fixKind, note string) (Experiment, error) {
	label = strings.TrimSpace(label)
	if label == "" || len(label) > 128 {
		return Experiment{}, fmt.Errorf("experiment label must be 1-128 bytes")
	}
	if len(note) > 4096 {
		return Experiment{}, fmt.Errorf("note exceeds 4096 bytes")
	}
	now := learnOutcomeClock().UTC().Format(time.RFC3339)
	result, err := s.db.Exec(`INSERT INTO experiments (label, sink_id, fix_kind, note, created_at)
		VALUES (?, ?, ?, ?, ?)`, label, sinkID, fixKind, note, now)
	if err != nil {
		return Experiment{}, fmt.Errorf("start experiment %q: %w", label, err)
	}
	id, err := result.LastInsertId()
	if err != nil {
		return Experiment{}, fmt.Errorf("read experiment id: %w", err)
	}
	if _, err := s.db.Exec(`INSERT INTO experiment_arms (experiment_id, arm, started_at)
		VALUES (?, ?, ?)`, id, experimentArmOn, now); err != nil {
		return Experiment{}, fmt.Errorf("open first arm: %w", err)
	}

View on GitHub (pinned to 81536f57b3)

Solutions

  1. Provide a non-empty label of at most 128 bytes
  2. Trim accidental whitespace-only labels in the caller
  3. Auto-generate a short slug label when the user supplies none
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at proxy/internal/store/learn_experiment.go:90 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of JuliusBrussee/caveman@81536f57b3 (2026-08-27). Data as JSON: /api/errors/eba822c9a5eb8dc9. Report an issue: GitHub.