{"record":{"id":"db10709010fd146d","repo":"Hmbown/CodeWhale","slug":"windows-list-windows-does-not-support-app-ref-or-window-id","errorCode":null,"errorMessage":"Windows list_windows does not support app_ref or window_id; omit them to list all windows","messagePattern":"Windows list_windows does not support app_ref or window_id; omit them to list all windows","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/win32.mjs","lineNumber":293,"sourceCode":"$arr = @([System.Windows.Forms.Screen]::AllScreens | ForEach-Object { [pscustomobject]@{ name = $_.DeviceName; primary = $_.Primary; x = $_.Bounds.X; y = $_.Bounds.Y; w = $_.Bounds.Width; h = $_.Bounds.Height } });\n@{ displays = $arr } | ConvertTo-Json -Depth 4 -Compress;`, { timeoutMs: 15_000 });\n      return d.displays.map((x, i) => ({ index: i + 1, name: x.name, points: { x: x.x, y: x.y, w: x.w, h: x.h }, pixels: { w: x.w, h: x.h }, scale: 1, main: !!x.primary }));\n    },\n    async switch_display({ index = 1 }) {\n      const displays = await this.list_displays();\n      if (!displays.some(d => d.index === index)) throw new ExecError(\"display index is out of range\");\n      activeDisplay = index;\n      return { activeDisplay };\n    },\n    list_apps: async () => {\n      const j = await psJson(`Add-Type -AssemblyName System.Windows.Forms;\n$out = Get-Process | Where-Object { $_.MainWindowTitle } | ForEach-Object { [pscustomobject]@{ name = $_.ProcessName; pid2 = $_.Id; title = $_.MainWindowTitle } } | ConvertTo-Json -Compress;\nif (-not $out) { $out = '[]' }\nWrite-Output ('{\"apps\": ' + $out + '}');`);\n      return { apps: (Array.isArray(j.apps) ? j.apps : [j.apps]).map((a) => ({ name: a.name, pid: a.pid2, title: a.title })) };\n    },\n    list_windows: async (args = {}) => {\n      if (Object.hasOwn(args, \"app_ref\") || Object.hasOwn(args, \"window_id\")) throw unsupportedSelector(\"Windows list_windows does not support app_ref or window_id; omit them to list all windows\");\n      const j = await psJson(`$ErrorActionPreference = 'Stop';\nAdd-Type -AssemblyName System.Windows.Forms;\nAdd-Type -TypeDefinition @'\nusing System;\nusing System.Text;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\npublic static class WinEnum {\n  [DllImport(\"user32.dll\")] static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);\n  [DllImport(\"user32.dll\")] static extern bool IsWindowVisible(IntPtr hWnd);\n  [DllImport(\"user32.dll\")] static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);\n  [DllImport(\"user32.dll\")] static extern int GetWindowTextLength(IntPtr hWnd);\n  [DllImport(\"user32.dll\")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid);\n  [DllImport(\"user32.dll\")] static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);\n  [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; }\n  delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n  public static List<string> List() {\n    var result = new List<string>();","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/win32.mjs#L275-L311","documentation":"The Windows (win32) backend of the computer-use plugin's list_windows only enumerates ALL top-level windows; it cannot filter by app_ref or window_id. The implementation guards at entry and throws unsupportedSelector if either key is present, because Win32 window enumeration produces a flat list with no selector-based lookup path.","triggerScenarios":"Calling the computer-use tool with action list_windows on Windows while passing app_ref (e.g. {name|pid|bundle_id}) or window_id in the arguments.","commonSituations":"Porting automation scripts written against the macOS backend (which supports selectors) to Windows; an LLM agent emitting the same arguments it used on another platform; copying a call that previously targeted a specific app's windows.","solutions":["Call list_windows with no app_ref or window_id arguments to get all windows.","Filter the returned windows client-side by title or owning process name to emulate the selector.","If you need app-scoped state instead, use get_app_state with app_ref: { name: <exact window title> }.","Use list_apps first to find the exact title/pid, then match against the full list_windows result."],"exampleFix":"// before\nawait computerUse({ action: \"list_windows\", app_ref: { name: \"Notepad\" } });\n// after\nconst all = await computerUse({ action: \"list_windows\" });\nconst windows = all.windows.filter(w => w.title === \"Notepad\");","handlingStrategy":"validation","validationCode":"if (args && (\"app_ref\" in args || \"window_id\" in args)) delete args.app_ref, delete args.window_id; // win32: list all, filter client-side","typeGuard":"const selectorFree = (a) => a == null || !(\"app_ref\" in a || \"window_id\" in a);","tryCatchPattern":"try { await listWindows(args) } catch (e) { if (String(e.message).includes(\"does not support\")) { args = {}; /* retry unfiltered */ } else throw e; }","preventionTips":["Branch on platform/backend name before choosing selector arguments","Filter list_windows results in code instead of via selectors on Windows","Keep a per-backend capability table for the computer-use tool"],"tags":["windows","computer-use","unsupported-selector","api-mismatch"],"backgroundTag":"unsupported-operation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}