{"record":{"id":"c8bbac808a124c7c","repo":"wavetermdev/waveterm","slug":"failed-to-get-terminal-scrollback-w","errorCode":null,"errorMessage":"failed to get terminal scrollback: %w","messagePattern":"failed to get terminal scrollback: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/tools_term.go","lineNumber":210,"sourceCode":"\t\t},\n\t\tToolAnyCallback: func(input any, toolUseData *uctypes.UIMessageDataToolUse) (any, error) {\n\t\t\tparsed, err := parseTermGetScrollbackInput(input)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tlineEnd := parsed.LineStart + parsed.Count\n\t\t\toutput, err := getTermScrollbackOutput(\n\t\t\t\ttabId,\n\t\t\t\tparsed.WidgetId,\n\t\t\t\twshrpc.CommandTermGetScrollbackLinesData{\n\t\t\t\t\tLineStart:   parsed.LineStart,\n\t\t\t\t\tLineEnd:     lineEnd,\n\t\t\t\t\tLastCommand: false,\n\t\t\t\t},\n\t\t\t)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to get terminal scrollback: %w\", err)\n\t\t\t}\n\t\t\treturn output, nil\n\t\t},\n\t}\n}\n\ntype TermCommandOutputToolInput struct {\n\tWidgetId string `json:\"widget_id\"`\n}\n\nfunc parseTermCommandOutputInput(input any) (*TermCommandOutputToolInput, error) {\n\tresult := &TermCommandOutputToolInput{}\n\n\tif input == nil {\n\t\treturn nil, fmt.Errorf(\"widget_id is required\")\n\t}\n\n\tinputBytes, err := json.Marshal(input)","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/tools_term.go#L192-L228","documentation":"The term_get_scrollback tool's ToolAnyCallback wraps any failure from getTermScrollbackOutput — which resolves the widget id to a full block id and issues TermGetScrollbackLinesCommand over the block's fe route — with this error. The root cause (block not found, no controller, fe route unavailable, RPC timeout after 5s) is preserved with %w; unwrap it to diagnose.","triggerScenarios":"term_get_scrollback invoked with a widget_id that cannot be resolved via wcore.ResolveBlockIdFromPrefix (bad prefix, wrong tab, block closed), or TermGetScrollbackLinesCommand failing: terminal block has no frontend controller, block route not connected, or the 5s timeout expires.","commonSituations":"AI agent using a widget id from a previous session after the terminal was closed/recreated; passing an id that belongs to a different tab; terminal pane still initializing so the fe route isn't registered yet; running headless where the block frontend isn't running.","solutions":["Unwrap the error to distinguish id-resolution failure from RPC failure","Verify the widget_id is a valid 8-character prefix of an existing terminal block in the current tab","List current widgets/tabs and retry with a fresh widget_id if the terminal was closed or restarted","Retry shortly after terminal creation — the block frontend route may not be registered yet","Check that the target block is actually a terminal widget with an active controller"],"exampleFix":"// before\noutput, err := getTermScrollbackOutput(tabId, parsed.WidgetId, rpcData)\nif err != nil { return nil, fmt.Errorf(\"failed to get terminal scrollback: %w\", err) }\n// after\noutput, err := getTermScrollbackOutput(tabId, parsed.WidgetId, rpcData)\nif err != nil {\n    return nil, fmt.Errorf(\"failed to get terminal scrollback for widget %s: %w\", parsed.WidgetId, err)\n} // then: check widget exists via block list before retrying","handlingStrategy":"try-catch","validationCode":"ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\nfullBlockId, err := wcore.ResolveBlockIdFromPrefix(ctx, tabId, widgetId)\nif err != nil {\n    return fmt.Errorf(\"widget %s not found in tab %s: %w\", widgetId, tabId, err)\n}","typeGuard":null,"tryCatchPattern":"output, err := getTermScrollbackOutput(tabId, widgetId, rpcData)\nif err != nil {\n    if isTimeoutErr(err) {\n        // fe route may not be ready yet; retry with backoff\n    }\n    return fmt.Errorf(\"term_get_scrollback failed for %s: %w\", widgetId, err)\n}","preventionTips":["Fetch fresh widget ids from the current tab rather than caching them across sessions","Wait for the terminal block to be fully initialized before reading scrollback","Confirm the block is a terminal type with an active frontend controller","Retry once on timeout — the 5s deadline can expire on slow/verbose terminals"],"tags":["rpc","terminal","scrollback","wave","timeout"],"backgroundTag":"rpc-call-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}