can1357/oh-my-pi · error · ToolError
Assertion failed
Error message
Assertion failed
What it means
The browser-run sandbox exposes an `assert(cond, text?)` helper to user scripts; when the condition is falsy it throws this ToolError so the run cell fails with an explicit assertion message. It exists so in-page invariant checks surface as tool errors naming the failed assertion rather than silent bad state downstream.
Source
Thrown at packages/coding-agent/src/tools/browser/tab-worker.ts:1293
this.#active = active;
let completed = false;
let returnValue: unknown;
let failure: { error: unknown } | undefined;
let runPage: RunPageScope | undefined;
try {
throwIfAborted(signal);
runPage = createRunPageScope(this.#requirePage());
const browser = this.#requireBrowser();
const tabApi = this.#createTabApi(msg.name, msg.timeoutMs, signal, msg.session, output, screenshots, active);
const runtime = this.#ensureRuntime(msg.session);
runtime.setCwd(msg.session.cwd);
const onFloatingRejection = (reason: unknown): void => this.#recordFloatingRejection(active, reason);
runtime.setRunScope({
page: bindRunFacade(runPage.page, signal, active.rejectionOwner, onFloatingRejection),
browser: bindRunFacade(browser, signal, active.rejectionOwner, onFloatingRejection),
tab: bindRunFacade(tabApi, signal, active.rejectionOwner, onFloatingRejection),
assert: (cond: unknown, text?: string): void => {
if (!cond) throw new ToolError(text ?? "Assertion failed");
},
// Both wait forms register in the in-flight map so a cell that dies while
// sleeping/polling names the culprit instead of a bare whole-cell timeout.
wait: (msOrPredicate: number | (() => unknown), opts?: WaitPredicateOptions): Promise<unknown> => {
const label = typeof msOrPredicate === "number" ? `wait(${msOrPredicate}ms)` : "wait(predicate)";
const resolved =
typeof msOrPredicate === "number"
? undefined
: { timeout: resolvePredicateTimeout(msg.timeoutMs, opts?.timeout), interval: opts?.interval };
return observeBrowserRunPromise(
this.#runOp(active, label, signal, Number.POSITIVE_INFINITY, sig =>
waitForRun(msOrPredicate, sig, resolved),
),
active.rejectionOwner,
onFloatingRejection,
);
},
});View on GitHub (pinned to 9690622007)
Solutions
- Read the supplied assertion text (or the default 'Assertion failed') and fix the violated condition in the run script
- Wait for the element/state before asserting (use the runtime's wait/predicate helpers)
- Pass a descriptive message to assert() so failures are diagnosable: `assert(el, 'login button present')`
- Re-run with snapshot/ariaSnapshot to inspect actual page state when the assertion is unexpected
Example fix
// before
assert(page.$('.price'), 'Assertion failed');
// after
await wait(() => page.$('.price'), { timeout: 5000 });
assert(page.$('.price'), 'price element should appear after load'); Defensive patterns
Strategy: try-catch
Validate before calling
// precondition check inside the run script before asserting
const el = page.$('.price');
if (!el) throw new Error('price element missing — check selector/page state before assert'); Try / catch
try {
await runCell(code);
} catch (err) {
if (err instanceof ToolError && err.message.includes('Assertion failed')) {
const snap = await tab.ariaSnapshot(); // inspect actual page state
logger.warn('run assertion failed', { snap });
} else throw err;
} Prevention
- Always pass a descriptive message to assert()
- Wait for elements/states before asserting on them
- Keep assertions on stable, locale-independent page properties
- Capture an ariaSnapshot in the failure path to debug unexpected assertions
When it happens
Trigger: User automation code inside a browser-run cell calls `assert(...)` with a condition that evaluated false — e.g. asserting a selector matched, an element's text equals an expectation, or a URL/state check after navigation.
Common situations: Page rendered differently than the script assumed (A/B variant, locale, login wall); element not yet present at assert time (missing wait); wrong selector; flaky async content.
Related errors
- Assertion failed
- Assertion failed
- ${error.message} (rethrown as ToolError from StructuredSubag
- pr://${repo}/${parsed.number}/diff/${index} resolved to a mi
- Plan mode is not active.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c2ea190827507f77.
Report an issue: GitHub.