vercel-labs/agent-browser · error
Provide at least one of: selector, text, urlPattern, loadSta
Error message
Provide at least one of: selector, text, urlPattern, loadState, jsCondition, timeMs.
What it means
The eve 'wait_for' tool builds a list of waits from six optional condition fields (selector, text, urlPattern, loadState, jsCondition, timeMs); timeoutMs is a modifier, not a condition. If every condition field is undefined the waits array is empty and execute() throws this message instead of running a pointless CLI call. Blank strings count as absent because optionalCondition preprocesses them to undefined.
Source
Thrown at packages/@agent-browser/eve/extension/tools/wait_for.ts:74
}
if (selector !== undefined) {
waits.push({ args: ["wait", selector], condition: `element ${selector}` });
}
if (text !== undefined) {
waits.push({ args: ["wait", "--text", text], condition: `text "${text}"` });
}
if (urlPattern !== undefined) {
waits.push({ args: ["wait", "--url", urlPattern], condition: `url ${urlPattern}` });
}
if (jsCondition !== undefined) {
waits.push({ args: ["wait", "--fn", jsCondition], condition: `js ${jsCondition}` });
}
if (timeMs !== undefined) {
// A fixed delay is its own duration; --timeout would override it.
waits.push({ args: ["wait", String(timeMs)], condition: `${timeMs}ms delay`, isDelay: true });
}
if (waits.length === 0) {
throw new Error(
"Provide at least one of: selector, text, urlPattern, loadState, jsCondition, timeMs.",
);
}
const cap = timeoutMs ?? 10_000;
const outcomes: WaitOutcome[] = [];
for (const wait of waits) {
const args = wait.isDelay ? wait.args : [...wait.args, "--timeout", String(cap)];
outcomes.push(await runWait(ctx, args, wait.condition));
}
return outcomes.length === 1 ? outcomes[0] : outcomes;
},
});
async function runWait(
ctx: BrowserToolContext,
args: readonly string[],
condition: string,
): Promise<WaitOutcome> {View on GitHub (pinned to 548b159b30)
Solutions
- Add at least one condition, e.g. tools.waitFor({ selector: '#done' }) or tools.waitFor({ timeMs: 1000 })
- For a plain delay use timeMs
- If you only wanted the default page-load wait, skip the tool entirely — navigation already waits for load
Example fix
// before
await tools.waitFor({ timeoutMs: 5000 });
// after
await tools.waitFor({ selector: "#done", timeoutMs: 5000 }); Defensive patterns
Strategy: validation
Validate before calling
const hasCondition =
[input.selector, input.text, input.urlPattern, input.loadState, input.jsCondition, input.timeMs]
.some((v) => v !== undefined && v !== "");
if (!hasCondition) {
throw new Error("wait_for needs at least one condition; use timeMs for a plain delay");
} Type guard
function hasWaitCondition(i: Record<string, unknown>): boolean {
return ["selector", "text", "urlPattern", "loadState", "jsCondition", "timeMs"]
.some((key) => i[key] !== undefined);
} Prevention
- Remember blank strings are treated as absent by the tool's preprocessor
- Use timeMs for fixed delays and real conditions for everything else
- Note navigation already waits for load — only wait for content that appears later
When it happens
Trigger: Calling wait_for with only timeoutMs; passing empty-string conditions (they are preprocessed away); models sending { } as a 'just wait' call without timeMs.
Common situations: Agent templates that always call wait_for after navigation; optional fields stripped by JSON round-trips; copy-pasted calls where the condition variable was empty.
Related errors
- The "${action}" action requires a value.
- The "${property}" property requires a selector.
- The "attr" property requires an attribute name.
- The "goto" action requires a url.
- Provide a direction to scroll, or a selector to scroll into
AI-assisted analysis of vercel-labs/agent-browser@548b159b30 (2026-08-16).
Data as JSON: /api/errors/a6be94bdc628ba24.
Report an issue: GitHub.