Hmbown/CodeWhale · error · Error
Invalid Engine batch.
Error message
Invalid Engine batch.
What it means
The `browser` tool's `click` action requires at least one valid target: a non-empty string `selector` or a `point` object with finite numeric x and y. Providing neither (missing, wrong type, empty/blank selector, or non-finite coordinates) throws this error.
Solutions
- Pass selector:"css-selector" for DOM targeting, or point:{x:Number,y:Number} for coordinate targeting.
- Verify the point coordinates are finite numbers (not strings/NaN) before calling.
- If the selector came from a failed lookup, re-resolve the element instead of clicking an empty selector.
Example fix
// before
resolveTool("browser", { action: "click", selector: "" });
// after
resolveTool("browser", { action: "click", selector: "#submit" }); Defensive patterns
Strategy: validation
Validate before calling
const hasSelector = typeof a.selector === "string" && a.selector.trim();
const hasPoint = a.point != null && Number.isFinite(a.point.x) && Number.isFinite(a.point.y);
if (!hasSelector && !hasPoint) {
throw new Error("click needs selector (non-empty string) or point {x:number,y:number}");
} Type guard
const hasClickTarget = (a) => (typeof a.selector === "string" && a.selector.trim().length > 0) || (a.point != null && Number.isFinite(a.point.x) && Number.isFinite(a.point.y));
Prevention
- Check point coordinates are finite numbers, not strings or NaN from a failed lookup.
- Never pass empty/blank selectors from failed DOM queries — re-resolve instead.
- Require exactly one of selector/point in your click call-site helper.
When it happens
Trigger: resolveTool("browser", {action:"click"}) with no target; selector: "" or " "; point: {x:NaN,y:200}; point: {x:"100",y:200} (string coords fail Number.isFinite); selector: {css:"#a"} (non-string).
Common situations: A click args object assembled from conditionally-filled fields where neither branch ran; coordinates computed from a failed element-lookup returning NaN; selector taken from an empty DOM query result; JSON round-trip turning numbers into strings.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Pet checkpoint exceeds its size limit.
- Engine pet clock jump.
- Invalid pet raster size.
- Native habitat exceeds 8 MiB.
- No pet segment was prepared.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/3904ef37be1b6266.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/pet_watch/pet-native.js:97
this.liveTape.reset();
this.segment = undefined;
this.engineTick = Math.round(this.world.frame.timeMs * 30 / 1000);
this.engine = new pet_engine_js_1.PetEngineTelemetry();
}
/** Resume a live host at the first unrecorded bucket. Keep every accepted
* interval, but never present its last observed frame as current evidence. */
resumeEngine() {
this.world.resumeObservation();
this.engineTick = Math.round(this.world.frame.timeMs * 30 / 1000);
this.engine = new pet_engine_js_1.PetEngineTelemetry();
this.world.voices = [];
return this.world.frame.timeMs;
}
observeEngine(metadataJSON, timeMs) { this.engine.observe(JSON.parse(metadataJSON), timeMs); }
observeEngineBatch(metadataJSON, timeMs) {
const events = JSON.parse(metadataJSON);
if (!Array.isArray(events) || events.length > 64)
throw new Error('Invalid Engine batch.');
const next = this.engine.clone();
for (const event of events)
next.observe(event, timeMs);
this.engine = next;
}
advanceEngine(timeMs, motion, waiting) {
const target = Math.floor(timeMs * 30 / 1000 + 1e-8);
if (!Number.isFinite(timeMs) || target < this.engineTick || target - this.engineTick > 300)
throw new Error('Engine pet clock jump.');
this.engine.confirmWaiting(timeMs, waiting);
const voices = [];
while (this.engineTick < target) {
if ((this.engineTick + 1) % 12 === 0)
this.world.acceptTelemetry(this.engine.bucket(Math.floor(this.engineTick / 12)));
this.world.step(1 / 30, { motion, sensitivity: 1 });
voices.push(...this.world.voices);
this.engineTick++;
}View on GitHub (pinned to 73e0f67d83)