JuliusBrussee/caveman · error
rewriter: theta must not be negative, got
Error message
rewriter: theta must not be negative, got %d
What it means
rewriter.New accepts cfg.Theta as the rewriting threshold; a zero value is replaced by DefaultTheta, but a negative value is rejected outright. Theta is a sampling/threshold parameter and a negative value has no meaning, so the constructor refuses to build a Client with one.
Solutions
- Pass a non-negative theta, or leave it 0/omitted so DefaultTheta is applied
- Map "unset" sentinels (like -1) to 0 before constructing Config
- Validate the parsed config value (>= 0) at load time with a clear message
- Check sign conventions if porting config from another tool
Example fix
// before
cfg := rewriter.Config{Provider: "openai", Model: "m", Theta: -1} // error
// after
theta := cfgRaw.Threshold
if theta < 0 {
theta = 0 // 0 means DefaultTheta
}
cfg := rewriter.Config{Provider: "openai", Model: "m", Theta: theta} Defensive patterns
Strategy: validation
Validate before calling
if cfg.Theta < 0 {
return fmt.Errorf("theta must be >= 0 (0 selects DefaultTheta=%d), got %d", rewriter.DefaultTheta, cfg.Theta)
} Try / catch
client, err := rewriter.New(cfg)
if err != nil {
if strings.Contains(err.Error(), "theta must not be negative") {
cfg.Theta = 0 // fall back to DefaultTheta
client, err = rewriter.New(cfg)
}
if err != nil { return err }
} Prevention
- Treat 0 as "unset -> DefaultTheta"; never use -1 as a sentinel for unset
- Clamp numeric config fields to their domain right after parsing
- Add a config-schema check (minimum: 0) for theta in CI
- Unit-test config loading with negative values to fail early
When it happens
Trigger: Calling rewriter.New(Config{Theta: <0}) — e.g. Theta: -1 — typically because the field was populated from user input, a config file, or an int that was defaulted with a sentinel of -1 meaning "unset".
Common situations: Config files using -1 as "use default"; arithmetic producing negative thresholds; copying a config from another tool with different sign conventions; test validation paths (TestNewValidation).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ccr max storage bytes must be positive
- arm must be or
- CAVEMAN_CCR_MAX_BYTES must be a positive integer
- compat upstream name
- githubapp: app id is required
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/17208ad6b60b01fa.
Report an issue: GitHub.
Appendix: source
Thrown at rewriter/rewriter.go:144
// gate was designed for.
func New(cfg Config) (*Client, error) {
provider := strings.ToLower(strings.TrimSpace(cfg.Provider))
if provider != providerAnthropic && provider != providerOpenAI {
return nil, fmt.Errorf("rewriter: unsupported provider %q", cfg.Provider)
}
model := strings.TrimSpace(cfg.Model)
if model == "" {
return nil, errors.New("rewriter: model is required")
}
if strings.TrimSpace(cfg.APIKey) == "" {
return nil, errors.New("rewriter: api key is required")
}
theta := cfg.Theta
if theta == 0 {
theta = DefaultTheta
}
if theta < 0 {
return nil, fmt.Errorf("rewriter: theta must not be negative, got %d", theta)
}
doer := cfg.HTTPDoer
if doer == nil {
doer = http.DefaultClient.Do
}
return &Client{provider: provider, model: model, apiKey: cfg.APIKey, theta: theta, doer: doer}, nil
}
// Rewrite condenses req.StepBytes, or explains why it did not.
//
// Gate 1 (invocation) skips the API call entirely when the step is at or under
// θ tokens. Gate 2 (application) plus the fidelity checks in Accept decide
// whether the completion may replace the original. Only an accepted result
// carries bytes; every other path returns an empty Rewritten and a reason.
func (c *Client) Rewrite(ctx context.Context, req Request) (Result, error) {
originalTokens := countTokens(req.StepBytes)
if originalTokens <= c.theta {
return Result{RejectReason: reasonBelowTheta}, nilView on GitHub (pinned to 3ee70a1026)