{"record":{"id":"e518904bcfe99d83","repo":"wavetermdev/waveterm","slug":"unable-to-find-client-w","errorCode":null,"errorMessage":"unable to find client: %w","messagePattern":"unable to find client: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wcore/layout.go","lineNumber":150,"sourceCode":"\t\t\tFocused:    layoutAction.Focused,\n\t\t}\n\t}\n\n\terr := QueueLayoutActionForTab(ctx, tabId, actions...)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to queue layout actions for portable layout: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc BootstrapStarterLayout(ctx context.Context) error {\n\tctx, cancelFn := context.WithTimeout(ctx, 2*time.Second)\n\tdefer cancelFn()\n\tclient, err := wstore.DBGetSingleton[*waveobj.Client](ctx)\n\tif err != nil {\n\t\tlog.Printf(\"unable to find client: %v\\n\", err)\n\t\treturn fmt.Errorf(\"unable to find client: %w\", err)\n\t}\n\n\tif len(client.WindowIds) < 1 {\n\t\treturn fmt.Errorf(\"error bootstrapping layout, no windows exist\")\n\t}\n\n\twindowId := client.WindowIds[0]\n\n\twindow, err := wstore.DBMustGet[*waveobj.Window](ctx, windowId)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting window: %w\", err)\n\t}\n\n\tworkspace, err := wstore.DBMustGet[*waveobj.Workspace](ctx, window.WorkspaceId)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting workspace: %w\", err)\n\t}\n","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wcore/layout.go#L132-L168","documentation":"BootstrapStarterLayout fetches the singleton Client object from the wave store. This error wraps a DBGetSingleton failure — either the Client record does not exist yet (ErrNotFound) or the store read failed. It is also logged before being returned.","triggerScenarios":"Calling BootstrapStarterLayout (e.g. from AgreeTos) before EnsureInitialData has run and created the Client singleton, or when the wstore read fails (corruption, IO error, ctx timeout — the call uses a 2s timeout).","commonSituations":"First launch ordering bug where bootstrap runs before CreateClient; corrupted or deleted wave store DB file; slow disk causing the 2-second context deadline to expire.","solutions":["Ensure EnsureInitialData (which creates the Client via CreateClient) runs before BootstrapStarterLayout","Check the log line 'unable to find client' for the wrapped cause (ErrNotFound vs IO/timeout)","Verify the wave store DB file exists and is not corrupted","If timeouts recur, check disk I/O health; the 2s deadline is fixed in the function"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// ensure client singleton exists before bootstrapping\nif _, err := wstore.DBGetSingleton[*waveobj.Client](ctx); err != nil {\n    return fmt.Errorf(\"client not initialized; run EnsureInitialData first: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := wcore.BootstrapStarterLayout(ctx); err != nil {\n    if strings.Contains(err.Error(), \"unable to find client\") {\n        // call EnsureInitialData or delay bootstrap\n    }\n}","preventionTips":["Always run EnsureInitialData before BootstrapStarterLayout","Allow >2s for startup on slow disks (deadline is fixed inside the function)","Check the accompanying log line to distinguish ErrNotFound from timeout/IO"],"tags":["waveterm","wstore","client","singleton","bootstrap"],"backgroundTag":"record-not-found","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}