wavetermdev/waveterm · error

unable to find client: %w

Error message

unable to find client: %w

What it means

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.

Source

Thrown at pkg/wcore/layout.go:150

			Focused:    layoutAction.Focused,
		}
	}

	err := QueueLayoutActionForTab(ctx, tabId, actions...)
	if err != nil {
		return fmt.Errorf("unable to queue layout actions for portable layout: %w", err)
	}

	return nil
}

func BootstrapStarterLayout(ctx context.Context) error {
	ctx, cancelFn := context.WithTimeout(ctx, 2*time.Second)
	defer cancelFn()
	client, err := wstore.DBGetSingleton[*waveobj.Client](ctx)
	if err != nil {
		log.Printf("unable to find client: %v\n", err)
		return fmt.Errorf("unable to find client: %w", err)
	}

	if len(client.WindowIds) < 1 {
		return fmt.Errorf("error bootstrapping layout, no windows exist")
	}

	windowId := client.WindowIds[0]

	window, err := wstore.DBMustGet[*waveobj.Window](ctx, windowId)
	if err != nil {
		return fmt.Errorf("error getting window: %w", err)
	}

	workspace, err := wstore.DBMustGet[*waveobj.Workspace](ctx, window.WorkspaceId)
	if err != nil {
		return fmt.Errorf("error getting workspace: %w", err)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Ensure EnsureInitialData (which creates the Client via CreateClient) runs before BootstrapStarterLayout
  2. Check the log line 'unable to find client' for the wrapped cause (ErrNotFound vs IO/timeout)
  3. Verify the wave store DB file exists and is not corrupted
  4. If timeouts recur, check disk I/O health; the 2s deadline is fixed in the function
Defensive patterns

Strategy: validation

Validate before calling

// ensure client singleton exists before bootstrapping
if _, err := wstore.DBGetSingleton[*waveobj.Client](ctx); err != nil {
    return fmt.Errorf("client not initialized; run EnsureInitialData first: %w", err)
}

Try / catch

if err := wcore.BootstrapStarterLayout(ctx); err != nil {
    if strings.Contains(err.Error(), "unable to find client") {
        // call EnsureInitialData or delay bootstrap
    }
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/e518904bcfe99d83. Report an issue: GitHub.