wavetermdev/waveterm · error
error updating client: %w
Error message
error updating client: %w
What it means
CreateWindow appends the new windowId to client.WindowIds and persists the Client singleton via wstore.DBUpdate; this error wraps the update failure. The window is already inserted, so failure here leaves an inconsistent state (window exists but is not registered with the client).
Source
Thrown at pkg/wcore/window.go:125
IsNew: true,
Pos: waveobj.Point{
X: 0,
Y: 0,
},
WinSize: *winSize,
}
err := wstore.DBInsert(ctx, window)
if err != nil {
return nil, fmt.Errorf("error inserting window: %w", err)
}
client, err := GetClientData(ctx)
if err != nil {
return nil, fmt.Errorf("error getting client: %w", err)
}
client.WindowIds = append(client.WindowIds, windowId)
err = wstore.DBUpdate(ctx, client)
if err != nil {
return nil, fmt.Errorf("error updating client: %w", err)
}
return GetWindow(ctx, windowId)
}
// CloseWindow closes a window and deletes its workspace if it is empty and not named.
// If fromElectron is true, it does not send an event to Electron.
func CloseWindow(ctx context.Context, windowId string, fromElectron bool) error {
log.Printf("CloseWindow %s\n", windowId)
window, err := GetWindow(ctx, windowId)
if err == nil {
log.Printf("got window %s\n", windowId)
deleted, _, err := DeleteWorkspace(ctx, window.WorkspaceId, false)
if err != nil {
log.Printf("error deleting workspace: %v\n", err)
}
if deleted {
log.Printf("deleted workspace %s\n", window.WorkspaceId)
}View on GitHub (pinned to a4447c1563)
Solutions
- Check the wrapped %w error for the write failure root cause
- Verify no second waveterm instance holds a lock on the DB
- Clean up the orphaned window row (DBDelete) since client registration failed
- Retry CreateWindow once the DB is writable
Example fix
// before
err = wstore.DBUpdate(ctx, client)
if err != nil {
return nil, fmt.Errorf("error updating client: %w", err)
}
// after
if err := wstore.DBUpdate(ctx, client); err != nil {
_ = wstore.DBDelete(ctx, waveobj.OType_Window, windowId) // roll back orphaned window
return nil, fmt.Errorf("error updating client: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := wcore.GetClientData(ctx); err != nil {
return fmt.Errorf("client record unreadable before window creation: %w", err)
} Try / catch
win, err := wcore.CreateWindow(ctx, winSize, workspaceId)
if err != nil && strings.Contains(err.Error(), "error updating client") {
// window inserted but not registered — clean up orphan
log.Printf("partial window creation: %v", err)
return err
} Prevention
- Serialize window creation (mutex) to avoid racing on the Client singleton
- Run a single waveterm process per state directory
- Reconcile client.WindowIds against actual windows on startup
When it happens
Trigger: wcore.CreateWindow where DBUpdate(ctx, client) fails after a successful read — DB write error, disk full, or the client record was deleted concurrently between read and update.
Common situations: Disk-full or permission issues mid-launch; concurrent window creation from multiple clients racing on the same Client singleton row; DB locked by another waveterm process.
Related errors
- error updating window: %w
- error deleting workspace: %w
- error creating workspace: %w
- error inserting window: %w
- error getting client: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/2d9d185a468d088e.
Report an issue: GitHub.