{"record":{"id":"8ae0373ba04c56d1","repo":"Hmbown/CodeWhale","slug":"windows-get-app-state-supports-only-app-ref-name-exact","errorCode":null,"errorMessage":"Windows get_app_state supports only app_ref: { name: exact window title }; PID, bundle_id and other references are unsupported","messagePattern":"Windows get_app_state supports only app_ref: (.+?); PID, bundle_id and other references are unsupported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/win32.mjs","lineNumber":362,"sourceCode":"        // one argument there, and transport that string as data into PowerShell.\n        const quoted = '\"' + urlArg.replace(/(\\\\*)\"/g, '$1$1\\\\\"').replace(/(\\\\+)$/g, '$1$1') + '\"';\n        const encoded = Buffer.from(quoted, \"utf16le\").toString(\"base64\");\n        argumentsScript = `$launchArg = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('${encoded}')); `;\n      }\n      // activate defaults to background on every platform: a minimized\n      // launch leaves the user's foreground window alone. Windows input is\n      // still shared-surface — this only controls the launch, not input.\n      const windowStyle = activate === true ? \"\" : \" -WindowStyle Minimized\";\n      const r = await psOk(`${argumentsScript}Start-Process -FilePath \"${target}\"${windowStyle}${urlArg != null ? \" -ArgumentList $launchArg\" : \"\"}; Write-Output '{\"launched\": true}'`, { timeoutMs: 20_000 });\n      if (r.code !== 0) throw new ExecError(`Start-Process failed: ${r.stderr.trim().slice(0, 200)}`, r);\n      return { launched: true, name: target, url: urlArg ?? null, activate: activate === true };\n    },\n    get_app_state: async (args = {}) => {\n      if (Object.hasOwn(args, \"window_id\")) throw unsupportedSelector(\"Windows get_app_state does not support window_id\");\n      const { app_ref, detail } = args;\n      if (Object.hasOwn(args, \"app_ref\") && (!app_ref || typeof app_ref !== \"object\" || Array.isArray(app_ref)\n        || Object.keys(app_ref).length !== 1 || !Object.hasOwn(app_ref, \"name\") || typeof app_ref.name !== \"string\" || !app_ref.name.trim())) {\n        throw unsupportedSelector(\"Windows get_app_state supports only app_ref: { name: exact window title }; PID, bundle_id and other references are unsupported\");\n      }\n      const filter = Buffer.from(app_ref?.name ?? \"\", \"utf16le\").toString(\"base64\");\n      const maxEls = detail === \"full\" ? 800 : 400;\n      const j = await psJson(`${UIA_PRELUDE}\n$max = ${maxEls};\n$filter = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('${filter}'));\n$root = [System.Windows.Automation.AutomationElement]::RootElement;\n$els = New-Object System.Collections.ArrayList;\n$found = $false; $truncated = $false; $appName = $null;\n$targets = @($root.FindAll([System.Windows.Automation.TreeScope]::Children, [System.Windows.Automation.Condition]::TrueCondition));\nif ($filter) {\n  $targets = @($targets | Where-Object { [string]::Equals($_.Current.Name, $filter, [StringComparison]::OrdinalIgnoreCase) });\n  if ($targets.Count -gt 1) { throw 'More than one application window has this exact name' }\n}\nforeach ($t in $targets) {\n  $nm = $t.Current.Name;\n  $found = $true; $appName = $nm;\n  $stack = New-Object System.Collections.Stack;","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/win32.mjs#L344-L380","documentation":"Windows get_app_state accepts only app_ref: { name: \"exact window title\" }. Any other app_ref shape — pid, bundle_id, extra keys, non-object, empty/blank name, or an array — throws unsupportedSelector, because the UIA lookup filters windows purely by title.","triggerScenarios":"app_ref missing, not an object, an array, containing keys other than name, name not a string, or name blank/whitespace; or passing { pid } / { bundle_id } forms valid on other backends.","commonSituations":"Reusing macOS-style { bundle_id } references on Windows; passing a process pid from list_apps instead of the window title; constructing app_ref programmatically and emitting an empty name.","solutions":["Pass exactly app_ref: { name: <exact window title> } with a non-empty trimmed string.","Copy the title verbatim from list_windows (win.title) or list_apps (apps[].title).","Do not include pid, bundle_id, or any second key in the app_ref object.","Match the app another way if only the pid is known: run list_windows and match the process name, then use its title."],"exampleFix":"// before\nawait computerUse({ action: \"get_app_state\", app_ref: { pid: 1234 } });\n// after\nawait computerUse({ action: \"get_app_state\", app_ref: { name: \"Untitled - Notepad\" } });","handlingStrategy":"type-guard","validationCode":"const ok = args?.app_ref && !Array.isArray(args.app_ref) && Object.keys(args.app_ref).length === 1 && typeof args.app_ref.name === \"string\" && args.app_ref.name.trim();","typeGuard":"function isTitleAppRef(a) { return !!a && typeof a === \"object\" && !Array.isArray(a) && Object.keys(a).length === 1 && \"name\" in a && typeof a.name === \"string\" && a.name.trim().length > 0; }","tryCatchPattern":"try { await getAppState(args) } catch (e) { if (String(e.message).includes(\"supports only app_ref\")) { args.app_ref = { name: await resolveWindowTitle(args) }; await getAppState(args); } else throw e; }","preventionTips":["Always copy the title verbatim from list_windows/list_apps output","Strip pid/bundle_id keys from app_ref when targeting Windows","Validate app_ref shape with a guard before dispatch"],"tags":["windows","computer-use","invalid-argument","uia"],"backgroundTag":"invalid-argument-value","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"}