{"record":{"id":"b736ea6d3f7321ef","repo":"wavetermdev/waveterm","slug":"error-getting-tab-w-b736ea","errorCode":null,"errorMessage":"error getting tab: %w","messagePattern":"error getting tab: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/service/workspaceservice/workspaceservice.go","lineNumber":184,"sourceCode":"\nfunc (svc *WorkspaceService) SetActiveTab_Meta() tsgenmeta.MethodMeta {\n\treturn tsgenmeta.MethodMeta{\n\t\tArgNames: []string{\"workspaceId\", \"tabId\"},\n\t}\n}\n\nfunc (svc *WorkspaceService) SetActiveTab(workspaceId string, tabId string) (waveobj.UpdatesRtnType, error) {\n\tctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)\n\tdefer cancelFn()\n\tctx = waveobj.ContextWithUpdates(ctx)\n\terr := wcore.SetActiveTab(ctx, workspaceId, tabId)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error setting active tab: %w\", err)\n\t}\n\t// check all blocks in tab and start controllers (if necessary)\n\ttab, err := wstore.DBMustGet[*waveobj.Tab](ctx, tabId)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting tab: %w\", err)\n\t}\n\tblockORefs := tab.GetBlockORefs()\n\tblocks, err := wstore.DBSelectORefs(ctx, blockORefs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting tab blocks: %w\", err)\n\t}\n\tupdates := waveobj.ContextGetUpdatesRtn(ctx)\n\tgo func() {\n\t\tdefer func() {\n\t\t\tpanichandler.PanicHandler(\"WorkspaceService:SetActiveTab:SendUpdateEvents\", recover())\n\t\t}()\n\t\twps.Broker.SendUpdateEvents(updates)\n\t}()\n\tvar extraUpdates waveobj.UpdatesRtnType\n\textraUpdates = append(extraUpdates, updates...)\n\textraUpdates = append(extraUpdates, waveobj.MakeUpdate(tab))\n\textraUpdates = append(extraUpdates, waveobj.MakeUpdates(blocks)...)\n\treturn extraUpdates, nil","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/service/workspaceservice/workspaceservice.go#L166-L202","documentation":"After switching the active tab, SetActiveTab fetches the Tab object with wstore.DBMustGet[*waveobj.Tab] to enumerate its blocks. If that fetch fails, the error is wrapped as \"error getting tab: %w\". Notably this can occur even though SetActiveTab succeeded, meaning the tabId exists for activation but could not be read from the store.","triggerScenarios":"Calling SetActiveTab with a tabId that is set as active but missing/deleted in the DB (DBMustGet panics-free path returns error), or a storage failure reading the Tab object.","commonSituations":"Race condition where the tab is deleted between the SetActiveTab core call and the DBMustGet; DB corruption; stale tab id.","solutions":["Unwrap the error to distinguish not-found from I/O failure","Re-fetch workspace state and retry SetActiveTab with a valid tabId","Check for concurrent CloseTab/DeleteTab races against the same tabId","Verify DB integrity"],"exampleFix":"// before\n_, err = wsSvc.SetActiveTab(wsId, tabId) // error getting tab\n// after\ntab, err := wstore.DBGet[*waveobj.Tab](ctx, tabId)\nif err == nil {\n    _, err = wsSvc.SetActiveTab(wsId, tabId)\n}","handlingStrategy":"validation","validationCode":"if _, err := wstore.DBGet[*waveobj.Tab](ctx, tabId); err != nil {\n    return fmt.Errorf(\"tab %s unreadable, cannot activate: %w\", tabId, err)\n}\n_, err = svc.SetActiveTab(workspaceId, tabId)","typeGuard":null,"tryCatchPattern":"rtn, err := svc.SetActiveTab(workspaceId, tabId)\nif err != nil {\n    if strings.Contains(err.Error(), \"error getting tab\") { /* DB read failure path */ }\n    return err\n}","preventionTips":["Avoid deleting tabs while another caller activates them","Monitor DB health; DBMustGet failures usually mean missing rows","Re-sync client state after any not-found error"],"tags":["go","workspace","tab","database"],"backgroundTag":"wrapped-error-propagation","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}