wavetermdev/waveterm · error
unable to get layout state for given id %s: %w
Error message
unable to get layout state for given id %s: %w
What it means
QueueLayoutAction looks up a LayoutState object in the wave object store by layoutStateId before appending actions. This error wraps the underlying wstore failure (typically ErrNotFound for a stale/unknown id, or a DB error). It means the layout state referenced by the caller does not exist or is not retrievable.
Source
Thrown at pkg/wcore/layout.go:85
waveobj.MetaKey_View: "term",
waveobj.MetaKey_Controller: "shell",
},
}, Focused: true},
}
}
func GetLayoutIdForTab(ctx context.Context, tabId string) (string, error) {
tabObj, err := wstore.DBGet[*waveobj.Tab](ctx, tabId)
if err != nil {
return "", fmt.Errorf("unable to get layout id for given tab id %s: %w", tabId, err)
}
return tabObj.LayoutState, nil
}
func QueueLayoutAction(ctx context.Context, layoutStateId string, actions ...waveobj.LayoutActionData) error {
layoutStateObj, err := wstore.DBGet[*waveobj.LayoutState](ctx, layoutStateId)
if err != nil {
return fmt.Errorf("unable to get layout state for given id %s: %w", layoutStateId, err)
}
for i := range actions {
if actions[i].ActionId == "" {
actions[i].ActionId = uuid.New().String()
}
}
if layoutStateObj.PendingBackendActions == nil {
layoutStateObj.PendingBackendActions = &actions
} else {
*layoutStateObj.PendingBackendActions = append(*layoutStateObj.PendingBackendActions, actions...)
}
err = wstore.DBUpdate(ctx, layoutStateObj)
if err != nil {
return fmt.Errorf("unable to update layout state with new actions: %w", err)
}View on GitHub (pinned to a4447c1563)
Solutions
- Verify the layoutStateId comes from Tab.LayoutState via GetLayoutIdForTab, not a hand-built or stale id
- Confirm the tab still exists and has not been closed/deleted before queueing actions
- If using QueueLayoutActionForTab, ensure the tab's LayoutState field is populated (set during tab creation)
- Check wstore DB health/file permissions if ErrNotFound is not the wrapped cause
Example fix
// before
err := wcore.QueueLayoutAction(ctx, someCachedId, action)
// after
layoutStateId, err := wcore.GetLayoutIdForTab(ctx, tabId)
if err != nil { return err }
err = wcore.QueueLayoutAction(ctx, layoutStateId, action) Defensive patterns
Strategy: validation
Validate before calling
layoutStateId, err := wcore.GetLayoutIdForTab(ctx, tabId)
if err != nil {
// tab or its layout state missing — abort before queueing
return err
} Try / catch
if err := wcore.QueueLayoutActionForTab(ctx, tabId, action); err != nil {
var nf error
if errors.Is(err, wstore.ErrNotFound) || strings.Contains(err.Error(), "unable to get layout state") {
// re-resolve id or recreate tab layout
}
} Prevention
- Always derive layoutStateId from Tab.LayoutState, never cache it across tab close/reopen
- Use QueueLayoutActionForTab instead of raw QueueLayoutAction
- Check errors.Is(err, wstore.ErrNotFound) to distinguish stale id from DB failure
When it happens
Trigger: Calling QueueLayoutAction (directly or via QueueLayoutActionForTab -> GetLayoutIdForTab) with a layoutStateId that is not in the DB, was deleted with its tab, or when the underlying wave store DB read fails (corruption/IO).
Common situations: Operating on a tab that was just closed so its LayoutState was removed; passing a tabId instead of a layoutStateId into QueueLayoutAction; racing the initial tab creation so the layout id is stale; disk/DB issues with the wave store.
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
- unable to update layout state with new actions: %w
- unable to queue layout actions for portable layout: %w
- object not found: %s
- unable to create block to apply portable layout to tab %s: %
- unable to find client: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/f33c2cc5e6733f00.
Report an issue: GitHub.