Hmbown/CodeWhale · error · Error

Unsupported pet expression version.

Error message

Unsupported pet expression version.

What it means

The Pet particle simulation constructor accepts only expression versions 1 and 2 (the default). This guard throws immediately when a caller passes any other expressionVersion, rejecting models the renderer cannot draw.

Solutions

  1. Pass 1 or 2 (or omit the argument to use the default 2) when constructing PetSim
  2. If the version came from persisted state, migrate or clamp it to a supported value before constructing
  3. Update the library if you need support for a newer expression version

Example fix

// before
new PetSim(points, seed, petFile.expressionVersion); // e.g. 3
// after
const version = petFile.expressionVersion === 1 ? 1 : 2;
new PetSim(points, seed, version);
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = [1, 2];
if (!SUPPORTED.includes(petVersion)) throw new Error(`Pet expression version ${petVersion} not supported; use 1 or 2`);

Type guard

function isSupportedExpressionVersion(v: unknown): v is 1 | 2 {
  return v === 1 || v === 2;
}

Try / catch

try {
  const pet = new PetSim(points, seed, version);
} catch (e) {
  if (e.message === 'Unsupported pet expression version.') {
    pet = new PetSim(points, seed, 2); // fall back to default version
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `new PetSim(points, seed, version)` with a version other than 1 or 2 — e.g. 0, 3, NaN, or a version read from a saved pet file that was produced by a newer build.

Common situations: Loading pets persisted by a newer app version that emits expression version 3; passing a user-controlled or config-supplied version number without clamping; typos like passing a string '2' that gets compared by !==.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/f45e7ce5ace6340f. Report an issue: GitHub.

Appendix: source

Thrown at pet/src/core/pet-sim.ts:286

// Fixed reduced-motion clock per channel, so ticks still point along the gait.
const STILL_T: Record<string, number> = {
  reasoning: 1.15, memory: 0.42, tool: 0.30, code: 0.18, filesystem: 0.48,
  network: 0.72, browser: 0.95, communication: 0.58, agent: 1.25,
  orchestration: 0.85, error: 0.35, human: 0.05, other: 0.90,
};

export class PetSim {
  readonly p: Particle[];
  private phase = 0;
  private clock = 0;
  private tear = 0;
  private prev: number;
  private col = [...REST_RGB];
  private cur: number;
  frame: Frame = { r: REST_RGB[0], g: REST_RGB[1], b: REST_RGB[2], alpha: 0.3, hollow: false, channel: 'reasoning', arch: 'gyre', work: 0 };

  constructor(points: [number, number][], seed = 0xC0FFEE, readonly expressionVersion: 1 | 2 = 2) {
    if (expressionVersion !== 1 && expressionVersion !== 2) throw new Error('Unsupported pet expression version.');
    const rand = mulberry32(seed);
    this.p = points.map(([hx, hy], i) => {
      const q: Particle = {
        x: hx, y: hy, vx: 0, vy: 0,
        s: rand(), jx: rand() * 6.283, jy: rand() * 6.283, pod: i % 6,
        hx, hy, ang: 0, rad: 0, tail: 0, tx: hx, ty: hy,
      };
      q.ang = Math.atan2(hy, hx);
      q.rad = Math.hypot(hx, hy);
      q.tail = clamp(((-hx - hy) * 0.5 + 0.22) / 0.62);
      return q;
    });
    this.cur = this.prev = CHANNEL_INDEX['reasoning'];
  }

  checkpoint(): PetSimCheckpoint {
    return { version: 1, expressionVersion: this.expressionVersion, body: this.p.map(p => [p.hx, p.hy, p.s]),
      particles: this.p.map(p => [p.x, p.y, p.vx, p.vy, p.jx, p.jy, p.tx, p.ty]),

View on GitHub (pinned to 433685b202)