jackwener/OpenCLI · error · TargetError
${resolution.message}
Error message
${resolution.message} What it means
When resolving a target reference inside the page (via injected JS), the in-page resolver can fail with a coded TargetError. This code re-raises the in-page failure as a TargetError carrying code, message, hint, candidates, and match count. The thrown message is exactly the resolver's resolution.message.
Source
Thrown at src/cli.ts:1026
$ opencli browser work unbind
`);
const originalBrowserDescription = browser.description();
/**
* Resolve a `<target>` (numeric ref or CSS selector) via the unified resolver.
* Returns the CSS match count so callers can propagate `matches_n` into the
* JSON envelope printed back to the agent.
*/
async function resolveRef(
page: Awaited<ReturnType<typeof getBrowserPage>>,
ref: string,
opts: ResolveOptions = {},
): Promise<{ matches_n: number; match_level: TargetMatchLevel }> {
const resolution = await page.evaluate(resolveTargetJs(ref, opts)) as
| { ok: true; matches_n: number; match_level: TargetMatchLevel }
| { ok: false; code: TargetErrorCode; message: string; hint: string; candidates?: string[]; matches_n?: number };
if (!resolution.ok) {
throw new TargetError({
code: resolution.code,
message: resolution.message,
hint: resolution.hint,
candidates: resolution.candidates,
matches_n: resolution.matches_n,
});
}
return { matches_n: resolution.matches_n, match_level: resolution.match_level };
}
/**
* Parse `--nth <n>` flag, returning the parsed 0-based index or a usage error.
* The surface mirrors `--depth` etc. in `browser get html --as json`: the flag
* is optional, must be a non-negative integer when present, and on failure we
* emit the structured error envelope rather than throwing past the command.
*/
function parseNthFlag(raw: unknown): number | null | { error: string } {
if (raw === undefined || raw === null || raw === '') return null;View on GitHub (pinned to 49907e53dc)
Solutions
- Read resolution.hint and candidates in the full TargetError to see near-misses and tighten the ref
- Wait for the element to exist (wait-for / polling) before resolving
- Make the target ref unambiguous (use a more specific selector or index)
- Retry after page load completes — transient DOM states cause resolution failures
Example fix
// before
await browser.click('button submit'); // ambiguous: two submit buttons
// after
await browser.click('button submit [data-testid=checkout]'); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check the element exists before resolving the target
const exists = await page.$(selector);
if (!exists) throw new Error(`Target not in DOM yet: ${ref}`); Type guard
function isFailedResolution(r: unknown): r is { ok: false; code: string; message: string; hint: string; candidates?: string[] } {
return typeof r === 'object' && r !== null && (r as { ok?: unknown }).ok === false;
} Try / catch
try {
await browser.click(ref);
} catch (e) {
if (e instanceof TargetError) {
console.error(`Target ${ref} failed (${e.code}): ${e.message}\nHint: ${e.hint}`);
if (e.candidates?.length) console.error('Near matches:', e.candidates);
}
throw e;
} Prevention
- Wait for the element/DOM to be ready before resolving targets
- Use specific, unambiguous selectors or refs with an index when matches can be multiple
- Log resolution.hint and candidates — they usually pinpoint the fix
- Re-resolve after navigation; stale targets from a previous page fail resolution
When it happens
Trigger: page.evaluate(resolveTargetJs(ref, opts)) returns { ok:false, ... } — i.e. the target reference could not be resolved: no matching element, ambiguous matches, unsupported selector, etc., depending on the TargetErrorCode.
Common situations: Selector typo or element not present in DOM at evaluation time; ambiguous text/role refs matching multiple elements; iframe/shadow-DOM content the resolver cannot see; page navigated away before evaluation.
Related errors
- coupang product extraction failed: ${error?.message || error
- Reuters article-detail failed inside the page: ${result.erro
- ${resolution.code}
- ${label} failed: ${error?.message ?? error}
- ${config.site} login
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/98d9ffdcf1a1c6f9.
Report an issue: GitHub.