wavetermdev/waveterm · error
update wavobj is nil
Error message
update wavobj is nil
What it means
ObjectService.UpdateObject refuses to proceed when the waveObj parameter is nil. The method derives an ORef from the object to locate it in wstore, and a nil object cannot produce one. This is a fail-fast guard against caller programming errors.
Source
Thrown at pkg/service/objectservice/objectservice.go:147
err = wstore.UpdateObjectMeta(ctx, *oref, meta, false)
if err != nil {
return nil, fmt.Errorf("error updating %q meta: %w", orefStr, err)
}
return waveobj.ContextGetUpdatesRtn(ctx), nil
}
func (svc *ObjectService) UpdateObject_Meta() tsgenmeta.MethodMeta {
return tsgenmeta.MethodMeta{
ArgNames: []string{"uiContext", "waveObj", "returnUpdates"},
}
}
func (svc *ObjectService) UpdateObject(uiContext waveobj.UIContext, waveObj waveobj.WaveObj, returnUpdates bool) (waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = waveobj.ContextWithUpdates(ctx)
if waveObj == nil {
return nil, fmt.Errorf("update wavobj is nil")
}
oref := waveobj.ORefFromWaveObj(waveObj)
found, err := wstore.DBExistsORef(ctx, *oref)
if err != nil {
return nil, fmt.Errorf("error getting object: %w", err)
}
if !found {
return nil, fmt.Errorf("object not found: %s", oref)
}
err = wstore.DBUpdate(ctx, waveObj)
if err != nil {
return nil, fmt.Errorf("error updating object: %w", err)
}
if (waveObj.GetOType() == waveobj.OType_Workspace) && (waveObj.(*waveobj.Workspace).Name != "") {
wps.Broker.Publish(wps.WaveEvent{
Event: wps.Event_WorkspaceUpdate})
}
if returnUpdates {View on GitHub (pinned to a4447c1563)
Solutions
- Check the object for nil before calling UpdateObject and return a meaningful error.
- Verify the upstream lookup succeeded and returned non-nil (confirm existence via wstore.DBExistsORef with a valid ORef).
- Trace where the nil originates; likely a deleted or never-created OID.
- If only the OID is known, fetch the object first, mutate, then update.
Example fix
// before
err := objectservice.UpdateObject(uiCtx, block, true)
// after
if block == nil {
return fmt.Errorf("cannot update: block %q not found", oid)
}
err := objectservice.UpdateObject(uiCtx, block, true) Defensive patterns
Strategy: validation
Validate before calling
if obj == nil {
return fmt.Errorf("cannot update: wave object is nil")
}
return svc.UpdateObject(uiCtx, obj, true) Type guard
func isNilWaveObj(w waveobj.WaveObj) bool {
return w == nil || reflect.ValueOf(w).IsNil()
} Prevention
- Never pass a lookup result to UpdateObject without a nil check.
- Return explicit errors from fetch helpers instead of bare nil.
- Log OIDs at fetch time so nil origins are traceable.
When it happens
Trigger: Calling UpdateObject(ctx, nil, true/false) - typically when a caller fetched a wave object, got nil back (failed lookup, absent object, failed unmarshal), and passed it through without checking.
Common situations: Frontend RPC handlers looking up a block/workspace by stale or deleted OID get nil, then call UpdateObject with it; scripts building WaveObj variants where a typed nil ended up in a non-nil interface.
Related errors
- nil wshrpc passed to wshclient
- object not found: %s
- error parsing command map: %w
- invalid oref string: %v
- cannot convert %T to %s (idx %d) error: %v
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/f7198f1eadf61518.
Report an issue: GitHub.