JuliusBrussee/caveman · error

open arm %q: %w

Error message

open arm %q: %w

What it means

The INSERT of the newly opened arm row into experiment_arms failed during an arm switch, so the previous arm was closed but the new arm was never opened. This is a database-level failure, not a validation error.

Source

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

	if err != nil {
		return Experiment{}, err
	}
	if experiment.StoppedAt != "" {
		return Experiment{}, fmt.Errorf("experiment %q is stopped", experiment.Label)
	}
	for _, existing := range experiment.Arms {
		if existing.EndedAt == "" && existing.Arm == arm {
			return experiment, nil
		}
	}
	now := learnOutcomeClock().UTC().Format(time.RFC3339)
	if _, err := s.db.Exec(`UPDATE experiment_arms SET ended_at = ?
		WHERE experiment_id = ? AND ended_at IS NULL`, now, experiment.id); err != nil {
		return Experiment{}, fmt.Errorf("close open arm: %w", err)
	}
	if _, err := s.db.Exec(`INSERT INTO experiment_arms (experiment_id, arm, started_at)
		VALUES (?, ?, ?)`, experiment.id, arm, now); err != nil {
		return Experiment{}, fmt.Errorf("open arm %q: %w", arm, err)
	}
	return s.LoadExperiment(label)
}

func (s *Store) StopExperiment(label string) (Experiment, error) {
	experiment, err := s.LoadExperiment(label)
	if err != nil {
		return Experiment{}, err
	}
	now := learnOutcomeClock().UTC().Format(time.RFC3339)
	if _, err := s.db.Exec(`UPDATE experiment_arms SET ended_at = ?
		WHERE experiment_id = ? AND ended_at IS NULL`, now, experiment.id); err != nil {
		return Experiment{}, fmt.Errorf("close open arm: %w", err)
	}
	if _, err := s.db.Exec(`UPDATE experiments SET stopped_at = ? WHERE id = ?`, now, experiment.id); err != nil {
		return Experiment{}, fmt.Errorf("stop experiment: %w", err)
	}
	return s.LoadExperiment(label)

View on GitHub (pinned to 81536f57b3)

Solutions

  1. Check the SQLite database file and schema for the experiment_arms table
  2. Inspect the wrapped driver error for the root cause
  3. Retry the switch; the next call will close the open arm and open the new one, repairing interval history
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at proxy/internal/store/learn_experiment.go:139 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/5b18595e712d1b59. Report an issue: GitHub.