Hmbown/CodeWhale · error · Error

Native habitat exceeds 8 MiB.

Error message

Native habitat exceeds 8 MiB.

What it means

The `browser` tool's `click` action targets exactly one element: either a CSS `selector` or a screen `point` {x,y}. Supplying both a valid selector and a valid point is rejected because the library cannot know which target is intended.

Solutions

  1. Delete either `selector` or `point` so exactly one target remains.
  2. Prefer `selector` when you know the element; keep `point` only for canvas/coordinate-based UIs.
  3. If both values come from state, add a call-site branch that picks one deterministically (e.g. selector wins).

Example fix

// before
resolveTool("browser", { action: "click", selector: "#submit", point: { x: 100, y: 200 } });
// after
resolveTool("browser", { action: "click", selector: "#submit" });
Defensive patterns

Strategy: validation

Validate before calling

const hasSelector = typeof selector === "string" && selector.trim();
const hasPoint = point != null && Number.isFinite(point.x) && Number.isFinite(point.y);
if (hasSelector && hasPoint) {
  delete args.point; // pick one target deterministically
}

Type guard

const clickTargetOk = (a) => {
  const s = typeof a.selector === "string" && a.selector.trim();
  const p = a.point != null && Number.isFinite(a.point.x) && Number.isFinite(a.point.y);
  return (s || p) && !(s && p);
};

Prevention

When it happens

Trigger: resolveTool("browser", {action:"click", selector:"#submit", point:{x:100,y:200}}) — both a non-empty string selector and a point with finite x and y present.

Common situations: Merging args from two clicks; a model hedging by giving both coordinate and selector; replaying a recorded click that stored both the resolved point and original selector; template that always fills both fields.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/cd931fb7db823aee. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tui/pet_watch/pet-native.js:76

        this.world.acceptTelemetry(packet);
        return true;
    }
    resetLiveInput() { this.liveTape.reset(); return this.resumeEngine(); }
    recording(withCheckpoint = false) { return JSON.stringify(this.world.recording(withCheckpoint)); }
    needsSegment() { return this.world.needsSegment; }
    prepareSegment() { this.segment = this.world.prepareSegment(); return JSON.stringify(this.segment.recording); }
    commitSegment() { if (!this.segment)
        throw new Error('No pet segment was prepared.'); this.segment.commit(); this.segment = undefined; }
    checkpoint() { return JSON.stringify(this.world.checkpoint()); }
    recordingChunk(index, completed = false) { return this.world.recordingChunk(index, completed); }
    restoreCheckpoint(text) {
        if (text.length > 512 * 1024)
            throw new Error('Pet checkpoint exceeds its size limit.');
        this.restoreRecording(JSON.stringify({ ...this.world.recording(false), checkpoint: JSON.parse(text) }));
    }
    restoreRecording(text) {
        if (text.length > 8 * 1024 * 1024)
            throw new Error('Native habitat exceeds 8 MiB.');
        const points = this.world.sim.p.map(p => [p.hx, p.hy]);
        this.world = pet_world_js_1.PetWorld.fromRecording(points, JSON.parse(text));
        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) {

View on GitHub (pinned to 73e0f67d83)