can1357/oh-my-pi · error · Error

Unsupported selector action ${action}

Error message

Unsupported selector action ${action}

What it means

The per-element eval script dispatches on an `action` string via a switch (click, setValue, scrollIntoView, select, uploadFile, ...). If the action name falls through every case, the script throws `Unsupported selector action <action>`. This guards against typos and actions not yet implemented in the in-page bridge.

Source

Thrown at packages/coding-agent/src/tools/browser/cmux/cmux-tab.ts:974

					}
					inputEvent(element);
					return selected;
				}
				case "uploadFile": {
					if (element.tagName !== "INPUT" || element.type !== "file") {
						throw new Error("tab.uploadFile() requires an <input type=file> element");
					}
					const transfer = new DataTransfer();
					for (const file of args.files || []) {
						const bytes = Uint8Array.from(atob(file.data), char => char.charCodeAt(0));
						transfer.items.add(new File([bytes], file.name, { type: file.type || "application/octet-stream" }));
					}
					element.files = transfer.files;
					inputEvent(element);
					return true;
				}
			}
			throw new Error("Unsupported selector action " + action);
		})()`;
		const result = (await this.#request("browser.eval", { script }, this.#runContext?.timeoutMs)) as CmuxEvalResult;
		return result.value as TResult;
	}

	async #waitForSelector(selector: string, timeoutMs: number): Promise<void> {
		const signal = this.#runContext?.signal;
		const spec = this.#selectorSpec(selector);
		const nativeSelector = this.#nativeSelector(spec);
		if (nativeSelector) {
			await this.#request("browser.wait", { selector: nativeSelector, timeout_ms: timeoutMs }, timeoutMs, signal);
			return;
		}
		const deadline = Date.now() + timeoutMs;
		while (Date.now() <= deadline) {
			if (await this.#selectorExists(spec)) return;
			await untilAborted(signal, () => Bun.sleep(100));
		}

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the action string against the implemented switch cases in cmux-tab.ts (click, setValue, scrollIntoView, select, uploadFile, etc.) and fix the typo/casing.
  2. Update the cmux daemon/browser bundle so client and in-page bridge versions match.
  3. If the action is genuinely missing, implement a new case in the eval script's switch or compose it from existing actions.

Example fix

// before
tab.action(el, 'setvalue', 'hello');
// after
tab.action(el, 'setValue', 'hello'); // exact camelCase action name
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED_ACTIONS = ['click','setValue','scrollIntoView','select','uploadFile'] as const;
if (!SUPPORTED_ACTIONS.includes(action as typeof SUPPORTED_ACTIONS[number]))
  throw new Error(`unknown selector action: ${action}`);

Type guard

type SelectorAction = typeof SUPPORTED_ACTIONS[number];
function isSelectorAction(a: string): a is SelectorAction { return (SUPPORTED_ACTIONS as readonly string[]).includes(a); }

Prevention

When it happens

Trigger: Passing a misspelled or unsupported action name into the tab's selector-action API (e.g. 'setvalue', 'check', 'hover'), or calling a newer action against an older cmux daemon whose eval script lacks that case.

Common situations: Version mismatch between client wrapper and daemon (action added upstream, daemon outdated); typo in a dynamically-built action string; refactoring renamed an action constant on one side only.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/d3d4e686f7314ded. Report an issue: GitHub.