{"record":{"id":"b506482fb2068e7c","repo":"wavetermdev/waveterm","slug":"no-active-tab","errorCode":null,"errorMessage":"no active tab","messagePattern":"no active tab","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/service/objectservice/objectservice.go","lineNumber":84,"sourceCode":"\t\torefObj, err := parseORef(orefStr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\torefArr = append(orefArr, *orefObj)\n\t}\n\treturn wstore.DBSelectORefs(ctx, orefArr)\n}\n\nfunc (svc *ObjectService) CreateBlock_Meta() tsgenmeta.MethodMeta {\n\treturn tsgenmeta.MethodMeta{\n\t\tArgNames:   []string{\"uiContext\", \"blockDef\", \"rtOpts\"},\n\t\tReturnDesc: \"blockId\",\n\t}\n}\n\nfunc (svc *ObjectService) CreateBlock(uiContext waveobj.UIContext, blockDef *waveobj.BlockDef, rtOpts *waveobj.RuntimeOpts) (string, waveobj.UpdatesRtnType, error) {\n\tif uiContext.ActiveTabId == \"\" {\n\t\treturn \"\", nil, fmt.Errorf(\"no active tab\")\n\t}\n\tctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)\n\tdefer cancelFn()\n\tctx = waveobj.ContextWithUpdates(ctx)\n\n\tblockData, err := wcore.CreateBlock(ctx, uiContext.ActiveTabId, blockDef, rtOpts)\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\n\treturn blockData.OID, waveobj.ContextGetUpdatesRtn(ctx), nil\n}\n\nfunc (svc *ObjectService) DeleteBlock_Meta() tsgenmeta.MethodMeta {\n\treturn tsgenmeta.MethodMeta{\n\t\tArgNames: []string{\"uiContext\", \"blockId\"},\n\t}\n}","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/service/objectservice/objectservice.go#L66-L102","documentation":"CreateBlock returns 'no active tab' when uiContext.ActiveTabId is an empty string. wcore.CreateBlock needs a parent tab to attach the new block to; without an active tab id the operation cannot proceed. It is a guard clause checked before any DB work.","triggerScenarios":"Calling ObjectService.CreateBlock with a zero-value UIContext, a UIContext built outside a window/tab context, or after the active tab was closed leaving ActiveTabId stale-empty.","commonSituations":"Automated/headless invocation without a UI; running the call during app startup before any tab exists; losing track of the active tab in multi-window scenarios.","solutions":["Set uiContext.ActiveTabId to a valid existing tab id before calling CreateBlock","Create/obtain a tab first (e.g. ensure the window has a tab) and use its id","Guard the call site: skip block creation when no tab is active"],"exampleFix":"// before\nsvc.CreateBlock(uiContext, blockDef, rtOpts)\n// after\nif uiContext.ActiveTabId == \"\" {\n    uiContext.ActiveTabId = getOrCreateActiveTabId(ctx)\n}\nsvc.CreateBlock(uiContext, blockDef, rtOpts)","handlingStrategy":"validation","validationCode":"if uiContext.ActiveTabId == \"\" { return fmt.Errorf(\"ActiveTabId must be set before CreateBlock\") }","typeGuard":"func hasActiveTab(uc waveobj.UIContext) bool { return uc.ActiveTabId != \"\" }","tryCatchPattern":"if uiContext.ActiveTabId == \"\" {\n    return errors.New(\"no active tab\")\n}\nblockId, _, err := svc.CreateBlock(uiContext, blockDef, rtOpts)\nif err != nil { return err }","preventionTips":["Ensure a window/tab exists before issuing block creation","Populate UIContext from the actual active window state","In headless flows, create a tab explicitly first"],"tags":["go","blocks","uicontext","precondition"],"backgroundTag":"missing-active-tab","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}