JuliusBrussee/caveman · error

sink is not a bounded recurring-context or reducible config…

Error message

sink %q is not a bounded recurring-context or reducible config sink

What it means

simulateLearnPlan can only compute arithmetic for sinks that are either recurring-context sinks with a bounded bytes4 estimate or reducible config sinks (isSimulatableConfigSink). Any other sink kind hits the final else branch and errors out, because no bounded estimation method exists for it. This is a deliberate fail-closed guard against extrapolating unbounded context growth.

Solutions

  1. Restrict the simulation selection to sinks the plan marks as recurring-context or reducible config sinks
  2. Check the plan row's method/basis to see which sinks support arithmetic before selecting them
  3. If the sink should be simulatable, ensure the scan classified it as bounded (or add support upstream)

Example fix

// before
store.BuildLearnSimulationFiltered(plan, allSinkIDs)
// after
var simulatable []string
for _, id := range allSinkIDs {
    if isSimulatable(plan.Sinks[id]) {
        simulatable = append(simulatable, id)
    }
}
store.BuildLearnSimulationFiltered(plan, simulatable)
Defensive patterns

Strategy: type-guard

Validate before calling

func isSimulatable(s PlanSink) bool {
    return s.Kind == "recurring-context" || isSimulatableConfigSink(s)
}

Type guard

func canSimulate(id string, byID map[string]PlanSink) bool {
    s, ok := byID[id]
    if !ok { return false }
    return s.Basis == "bytes4_estimate" || isSimulatableConfigSink(s)
}

Prevention

When it happens

Trigger: Passing a sink id to BuildLearnSimulationFiltered whose sink kind is neither a bounded recurring-context sink (bytes4_estimate path) nor a simulatable config sink, e.g. a recall-style or unbounded-growth sink.

Common situations: Selecting all plan sinks in a bulk simulation; a new sink kind was added to the plan but simulation support was not; confusing an establish-only sink with a simulatable one.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/68f90181ffe8d718. Report an issue: GitHub.

Appendix: source

Thrown at proxy/internal/store/learn_simulate.go:107

			owners[key] = id
		}
	}

	var total int64
	hasSummable := false
	totalValid := true
	for _, id := range ids {
		sink := byID[id]
		row := LearnSimulationRow{SinkID: id}
		if strings.HasPrefix(id, "recurring_context:repaste:") {
			row.Method = "occurrence_sum"
			row.Basis = "bytes4_estimate"
			row.Caveats = []string{"Arithmetic retains one largest observed occurrence and charges one standard pointer for every observed occurrence; recall cost is unavailable here, so real apply still requires the net-token-negative gate."}
		} else if isSimulatableConfigSink(sink) {
			row.Method = "per_turn_times_observed_turns"
			row.Caveats = []string{fmt.Sprintf("Would not have been established across the %d provider-counted turns actually scanned; no future turn is included.", observedTurns)}
		} else {
			return LearnSimulation{}, fmt.Errorf("sink %q is not a bounded recurring-context or reducible config sink", id)
		}

		if key := simulationOverlapKey(sink); key != "" && owners[key] != id {
			row.Caveats = append(row.Caveats, fmt.Sprintf("Excluded from arithmetic because it overlaps %s on %s; counting both would double-count.", owners[key], key))
			out.Rows = append(out.Rows, row)
			continue
		}

		var skipped int64
		if row.Method == "occurrence_sum" {
			totalTokens, totalOK := int64Evidence(sink.Evidence["occurrence_tokens_total"])
			largest, largestOK := int64Evidence(sink.Evidence["block_tokens"])
			occurrences, occurrencesOK := int64Evidence(sink.Evidence["occurrences_total"])
			if !totalOK || !largestOK || !occurrencesOK || occurrences <= 0 {
				row.Caveats = append(row.Caveats, "Required occurrence totals were unavailable; no arithmetic emitted.")
				out.Rows = append(out.Rows, row)
				continue
			}

View on GitHub (pinned to 3ee70a1026)