wavetermdev/waveterm · error
SetPath: Remove and CombineFn are mutually exclusive
Error message
SetPath: Remove and CombineFn are mutually exclusive
What it means
SetPath validates SetPathOpts before applying a path operation. Because Remove deletes the value at the path, it makes no sense to also supply CombineFn (which merges an existing value with a new one), so supplying both is rejected outright with this error. It is a pure API-misuse guard — the data is untouched.
Source
Thrown at pkg/ijson/ijson.go:234
type SetPathOpts struct {
Budget int // Budget 0 is unlimited (to set a 0 value, use -1)
Force bool
Remove bool
CombineFn CombiningFunc
}
func SetPathNoErr(data any, path Path, value any, opts *SetPathOpts) any {
ret, _ := SetPath(data, path, value, opts)
return ret
}
func SetPath(data any, path Path, value any, opts *SetPathOpts) (any, error) {
if opts == nil {
opts = &SetPathOpts{}
}
if opts.Remove && opts.CombineFn != nil {
return nil, fmt.Errorf("SetPath: Remove and CombineFn are mutually exclusive")
}
if opts.Remove && value != nil {
return nil, fmt.Errorf("SetPath: Remove and value are mutually exclusive")
}
return setPathInternal(data, pathWithPos{Path: path, Index: 0}, value, *opts)
}
func checkAndModifyBudget(opts *SetPathOpts, pp pathWithPos, cost int) bool {
if opts.Budget == 0 {
return true
}
opts.Budget -= cost
if opts.Budget < 0 {
return false
}
if opts.Budget == 0 {
// 0 is weird since it means unlimited, so we set it to -1 to fail the next operation
opts.Budget = -1View on GitHub (pinned to a4447c1563)
Solutions
- Remove CombineFn from the options when doing a delete, keeping only Remove: true.
- Remove the Remove flag when you intend to merge with CombineFn.
- If options come from user flags, validate exclusivity at the CLI/config layer before calling SetPath.
Example fix
// before
opts := &ijson.SetPathOpts{Remove: true, CombineFn: combineFn}
_, err := ijson.SetPath(data, path, nil, opts) // mutually exclusive
// after
opts := &ijson.SetPathOpts{Remove: true} // delete: no CombineFn, no value
_, err := ijson.SetPath(data, path, nil, opts) Defensive patterns
Strategy: validation
Validate before calling
func safeOpts(opts *ijson.SetPathOpts) error {
if opts != nil && opts.Remove && opts.CombineFn != nil {
return errors.New("Remove and CombineFn cannot be used together")
}
return nil
}
if err := safeOpts(opts); err != nil { return err } Try / catch
result, err := ijson.SetPath(data, path, value, opts)
if err != nil {
if strings.Contains(err.Error(), "mutually exclusive") {
opts.CombineFn = nil // fall back to plain removal
result, err = ijson.SetPath(data, path, nil, opts)
}
if err != nil { return err }
} Prevention
- Treat Remove as a mode of its own: when set, force value=nil and CombineFn=nil.
- Centralize option construction in one helper so exclusivity is enforced in one place.
- Add a unit test for every combination of SetPathOpts fields you allow.
- When options come from flags/config, validate exclusivity at parse time with a clear user-facing message.
When it happens
Trigger: Calling SetPath with opts where opts.Remove == true AND opts.CombineFn != nil, e.g. ijson.SetPath(data, path, nil, &ijson.SetPathOpts{Remove: true, CombineFn: func(a, b any) any {...}}). Callers SetPathNoErr, ApplyCommand, and TestSetPath funnel through here so any of them can surface it.
Common situations: Options structs assembled dynamically (flags/config) where Remove and a combine callback are both set by accident; copy-pasted option literals extended with Remove without removing CombineFn.
Related errors
- Image too large (>5MB)
- Unsupported or invalid image type: ${blob.type}
- Invalid CSS color: ${String(color)}
- Invalid CSS color: ${color}
- ai:model is required
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/4635325415115545.
Report an issue: GitHub.