{"record":{"id":"58360e65765da423","repo":"wavetermdev/waveterm","slug":"error-getting-window-w","errorCode":null,"errorMessage":"error getting window: %w","messagePattern":"error getting window: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/service/windowservice/windowservice.go","lineNumber":34,"sourceCode":"\t\"github.com/wavetermdev/waveterm/pkg/wstore\"\n)\n\nconst DefaultTimeout = 2 * time.Second\n\ntype WindowService struct{}\n\nfunc (svc *WindowService) GetWindow_Meta() tsgenmeta.MethodMeta {\n\treturn tsgenmeta.MethodMeta{\n\t\tArgNames: []string{\"windowId\"},\n\t}\n}\n\nfunc (svc *WindowService) GetWindow(windowId string) (*waveobj.Window, error) {\n\tctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)\n\tdefer cancelFn()\n\twindow, err := wstore.DBGet[*waveobj.Window](ctx, windowId)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting window: %w\", err)\n\t}\n\treturn window, nil\n}\n\nfunc (svc *WindowService) CreateWindow_Meta() tsgenmeta.MethodMeta {\n\treturn tsgenmeta.MethodMeta{\n\t\tArgNames: []string{\"ctx\", \"winSize\", \"workspaceId\"},\n\t}\n}\n\nfunc (svc *WindowService) CreateWindow(ctx context.Context, winSize *waveobj.WinSize, workspaceId string) (*waveobj.Window, error) {\n\twindow, err := wcore.CreateWindow(ctx, winSize, workspaceId)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating window: %w\", err)\n\t}\n\treturn window, nil\n}\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/service/windowservice/windowservice.go#L16-L52","documentation":"WindowService.GetWindow fetches a Window object from the wstore object database by OID, wrapped in this error when DBGet fails — typically because no window with that OID exists, or a DB/timeout error occurred. The original wstore error is preserved via %w for errors.Is/As inspection.","triggerScenarios":"Calling GetWindow with a windowId that does not exist in the DB (deleted window, wrong OID, empty string), or with a valid-shaped OID whose object is not of type window; also a DB timeout (DefaultTimeout) or underlying wstore failure.","commonSituations":"Frontend holding a stale window id after the window was closed; a race where the window is closed between listing and fetching; copy/pasted or guessed OIDs in scripts/tests; backend DB corruption or migration issues.","solutions":["Verify windowId is a real, currently-open window OID (e.g. from GetWindows/GetWindowList) before calling","Handle the not-found case: treat it as the window being gone and refresh the window list instead of retrying with the same id","Unwrap the %w error to distinguish wstore not-found from timeout/DB errors and handle each appropriately","If stale ids are common, subscribe to wps events for window deletion to invalidate cached ids"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const known = await WindowService.GetWindows();\nif (!known.some(w => w.OID === windowId)) throw new Error(`window ${windowId} does not exist`);","typeGuard":"function isKnownWindow(w: waveobj.Window | undefined, id: string): w is waveobj.Window { return w != null && w.OID === id; }","tryCatchPattern":"window, err := WindowService.GetWindow(windowId)\nif err != nil {\n    var nf *wstore.NotFoundError\n    if errors.As(err, &nf) { return refreshWindowList() }\n    return fmt.Errorf(\"get window %s: %w\", windowId, err)\n}","preventionTips":["Subscribe to window deletion wps events to invalidate cached window ids","Always obtain window ids from live queries, never persisted snapshots","Check the window still exists after user interaction before further calls on it"],"tags":["window","database","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"}