{"record":{"id":"bb2e64f2e7c61d94","repo":"wavetermdev/waveterm","slug":"error-updating-workspace-w","errorCode":null,"errorMessage":"error updating workspace: %w","messagePattern":"error updating workspace: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/service/workspaceservice/workspaceservice.go","lineNumber":49,"sourceCode":"func (svc *WorkspaceService) CreateWorkspace(ctx context.Context, name string, icon string, color string, applyDefaults bool) (string, error) {\n\tnewWS, err := wcore.CreateWorkspace(ctx, name, icon, color, applyDefaults, false)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error creating workspace: %w\", err)\n\t}\n\treturn newWS.OID, nil\n}\n\nfunc (svc *WorkspaceService) UpdateWorkspace_Meta() tsgenmeta.MethodMeta {\n\treturn tsgenmeta.MethodMeta{\n\t\tArgNames: []string{\"ctx\", \"workspaceId\", \"name\", \"icon\", \"color\", \"applyDefaults\"},\n\t}\n}\n\nfunc (svc *WorkspaceService) UpdateWorkspace(ctx context.Context, workspaceId string, name string, icon string, color string, applyDefaults bool) (waveobj.UpdatesRtnType, error) {\n\tctx = waveobj.ContextWithUpdates(ctx)\n\t_, updated, err := wcore.UpdateWorkspace(ctx, workspaceId, name, icon, color, applyDefaults)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error updating workspace: %w\", err)\n\t}\n\tif !updated {\n\t\treturn nil, nil\n\t}\n\n\twps.Broker.Publish(wps.WaveEvent{\n\t\tEvent: wps.Event_WorkspaceUpdate,\n\t})\n\n\tupdates := waveobj.ContextGetUpdatesRtn(ctx)\n\tgo func() {\n\t\tdefer func() {\n\t\t\tpanichandler.PanicHandler(\"WorkspaceService:UpdateWorkspace:SendUpdateEvents\", recover())\n\t\t}()\n\t\twps.Broker.SendUpdateEvents(updates)\n\t}()\n\treturn updates, nil\n}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/service/workspaceservice/workspaceservice.go#L31-L67","documentation":"WorkspaceService.UpdateWorkspace applies name/icon/color changes via wcore.UpdateWorkspace and wraps failures with this error. It returns nil,nil when nothing changed (updated=false). Failures usually come from an unknown workspaceId or invalid field values.","triggerScenarios":"UpdateWorkspace called with a workspaceId that does not exist (or was deleted), an invalid/empty name, or malformed icon/color values; the wrapped wcore error is preserved for unwrapping.","commonSituations":"Editing a workspace that was concurrently deleted in another window; frontend sending stale workspace state after external modification; UI validation gaps letting empty names through; scripts mass-updating workspaces with one bad OID.","solutions":["Confirm workspaceId exists (GetWorkspace) before updating; if not found, refresh the workspace list","Validate name/icon/color inputs on the caller side to match wcore's validation rules","Re-read the current workspace and merge changes instead of blind-overwriting with stale values","Unwrap the %w error to distinguish not-found from validation vs persistence failures"],"exampleFix":"// before\nWorkspaceService.UpdateWorkspace(ctx, deletedWsId, \"new-name\", \"terminal\", \"blue\", false)\n// after\nif _, err := WorkspaceService.GetWorkspace(wsId); err == nil {\n    WorkspaceService.UpdateWorkspace(ctx, wsId, \"new-name\", \"terminal\", \"blue\", false)\n}","handlingStrategy":"validation","validationCode":"const exists = await WorkspaceService.GetWorkspace(workspaceId).catch(() => null);\nif (!exists) throw new Error(`workspace ${workspaceId} no longer exists`);\nif (!name || !name.trim()) throw new Error(\"workspace name required\");","typeGuard":"function workspaceStillExists(ws: waveobj.Workspace | null | undefined, id: string): ws is waveobj.Workspace {\n  return ws != null && ws.OID === id;\n}","tryCatchPattern":"updates, err := WorkspaceService.UpdateWorkspace(ctx, wsId, name, icon, color, applyDefaults)\nif err != nil {\n    if strings.Contains(err.Error(), \"not found\") { return refreshWorkspaces() }\n    return fmt.Errorf(\"update workspace: %w\", err)\n}\nif updates == nil { /* no changes; skip publish */ }","preventionTips":["Re-read the workspace before saving edits to avoid overwriting concurrent changes","Handle the nil-updates (unchanged) return path distinctly from errors","Refresh workspace list after not-found errors instead of retrying the same id"],"tags":["workspace","update","not-found"],"backgroundTag":"waveobj-not-found","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}