wavetermdev/waveterm · error

error creating workspace: %w

Error message

error creating workspace: %w

What it means

CreateWindow with an empty workspaceId first creates a brand-new workspace via CreateWorkspace; this error wraps any failure of that creation. The window itself is never created, so callers receive nil and must handle the wrapped DB error.

Source

Thrown at pkg/wcore/window.go:87

	return ws, nil
}

func GetWindow(ctx context.Context, windowId string) (*waveobj.Window, error) {
	window, err := wstore.DBMustGet[*waveobj.Window](ctx, windowId)
	if err != nil {
		log.Printf("error getting window %q: %v\n", windowId, err)
		return nil, err
	}
	return window, nil
}

func CreateWindow(ctx context.Context, winSize *waveobj.WinSize, workspaceId string) (*waveobj.Window, error) {
	log.Printf("CreateWindow %v %v\n", winSize, workspaceId)
	var ws *waveobj.Workspace
	if workspaceId == "" {
		ws1, err := CreateWorkspace(ctx, "", "", "", false, false)
		if err != nil {
			return nil, fmt.Errorf("error creating workspace: %w", err)
		}
		ws = ws1
	} else {
		ws1, err := GetWorkspace(ctx, workspaceId)
		if err != nil {
			return nil, fmt.Errorf("error getting workspace: %w", err)
		}
		ws = ws1
	}
	windowId := uuid.NewString()
	if winSize == nil {
		winSize = &waveobj.WinSize{
			Width:  0,
			Height: 0,
		}
	}
	window := &waveobj.Window{
		OID:         windowId,

View on GitHub (pinned to a4447c1563)

Solutions

  1. Inspect the wrapped %w error for the root DB failure
  2. Verify the waveterm state directory is writable and the DB is not corrupted
  3. Ensure only one initialization path runs at startup (avoid concurrent EnsureInitialData/CreateWindow)
  4. Retry window creation after the DB is accessible

Example fix

// before
ws1, err := CreateWorkspace(ctx, "", "", "", false, false)
if err != nil {
	return nil, fmt.Errorf("error creating workspace: %w", err)
}
// after
ws1, err := CreateWorkspace(ctx, "", "", "", false, false)
if err != nil {
	return nil, fmt.Errorf("error creating workspace for new window: %w", err)
}
log.Printf("created workspace %s for new window", ws1.OID)
Defensive patterns

Strategy: retry

Validate before calling

wsList, err := wstore.DBGetAllObjsByType[*waveobj.Workspace](ctx, waveobj.OType_Workspace)
if err != nil {
	return fmt.Errorf("DB not readable, cannot create window: %w", err)
}

Try / catch

win, err := wcore.CreateWindow(ctx, winSize, "")
if err != nil {
	if strings.Contains(err.Error(), "error creating workspace") {
		time.Sleep(200 * time.Millisecond)
		win, err = wcore.CreateWindow(ctx, winSize, "") // one retry
	}
	if err != nil {
		return err
	}
}

Prevention

When it happens

Trigger: wcore.CreateWindow(ctx, winSize, "") when the internal CreateWorkspace(ctx, "", "", "", false, false) fails — DB insert error for the new workspace object, DB unavailable, or singleton/client setup failure.

Common situations: First-launch bootstrap when the state DB cannot be written (permissions on ~/.waveterm, read-only disk); corrupted DB rejecting inserts; EnsureInitialData racing with another startup path creating client/workspace singletons.

Related errors


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