{"record":{"id":"7e1f1ca5b16f0550","repo":"Hmbown/CodeWhale","slug":"invalid-pet-random-stream","errorCode":null,"errorMessage":"Invalid pet random stream.","messagePattern":"Invalid pet random stream\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/pet_watch/pet-native.js","lineNumber":728,"sourceCode":"        || ![s.roamX, s.roamY, s.flip].every(n => Number.isFinite(n) && Math.abs(n) <= 1))\n        throw new Error('Invalid pet state.');\n}\nconst hex2rgb = (h) => [parseInt(h.slice(1, 3), 16), parseInt(h.slice(3, 5), 16), parseInt(h.slice(5, 7), 16)];\nconst RGB = exports.CHANNELS.map(c => hex2rgb(c.color));\nconst UNKNOWN_RGB = hex2rgb('#738492');\nconst REST_RGB = [122, 214, 240];\n// mulberry32 — a 32-bit seeded PRNG tiny enough to port by hand correctly.\nfunction mulberry32(seed) {\n    let a = seed >>> 0;\n    return Object.assign(() => {\n        a = (a + 0x6D2B79F5) >>> 0;\n        let t = a;\n        t = Math.imul(t ^ (t >>> 15), t | 1);\n        t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n        return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n    }, { state: () => a, restore: (state) => {\n            if (!Number.isSafeInteger(state) || state < 0 || state > 0xffffffff)\n                throw new Error('Invalid pet random stream.');\n            a = state;\n        } });\n}\n/** Work reorganizes the same particles; no new random draws or invented facts.\n * These are expressive fields, not diagrams of unobserved network/file topology. */\nfunction fieldTarget(q, t, act, att, key) {\n    const u = q.s * 2 - 1, lane = q.pod - 2.5, a = q.s * Math.PI * 2;\n    const flow = t * (.35 + act * .65);\n    if (key === 'reasoning') {\n        const ring = .34 + .105 * Math.cos(a * 3 + flow + lane * .18);\n        return [ring * Math.cos(a * 2 + flow * .3), ring * Math.sin(a * 2 + flow * .3) * .7 + .10 * Math.sin(a * 3 + flow)];\n    }\n    if (key === 'memory')\n        return [.46 * Math.cos(a + lane * .1 + flow * .25), lane * .082 + .052 * Math.sin(a * 2 + flow)];\n    if (key === 'code')\n        return [u * .57, lane * .066 + .12 * Math.sin(u * 7 + flow * 2 + q.pod * Math.PI / 3)];\n    if (key === 'filesystem') {\n        const branch = Math.max(0, (u + .3) / 1.3);","sourceCodeStart":710,"sourceCodeEnd":746,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L710-L746","documentation":"mulberry32 creates a seeded PRNG used by the pet renderer and exposes a restore(state) method to resume a previous random stream. The stream state must be a single unsigned 32-bit safe integer; anything else would corrupt the PRNG, so restore throws 'Invalid pet random stream.'","triggerScenarios":"Calling petRandom.restore(state) with a non-integer, negative number, or a value > 0xffffffff (e.g. a float captured by serializing state, a state from a different PRNG, or a state stored as a string).","commonSituations":"Restoring a checkpoint saved by an older build whose state width differed; passing mulberry32 state through JSON round-trips that turned integers into floats or strings; sharing state generated by another RNG like xorshift.","solutions":["Inspect the value passed to restore(); log it and confirm Number.isSafeInteger(v) && v >= 0 && v <= 0xffffffff.","If the state came from serialization, coerce with `state >>> 0` before restoring, or clamp/reject at the save site.","If the state was produced by a different RNG, re-seed with the original seed (mulberry32(seed)) instead of restoring foreign state.","Regenerate the pet with a fresh seed if the previous stream state is unrecoverable."],"exampleFix":"// before\npet.random.restore(parsed.state); // parsed.state is 4294967296.5 after JSON round-trip\n// after\nif (Number.isSafeInteger(parsed.state) && parsed.state >= 0 && parsed.state <= 0xffffffff) {\n  pet.random.restore(parsed.state);\n} else {\n  pet.random.restore(0xC0FFEE); // re-seed fallback\n}","handlingStrategy":"validation","validationCode":"function validPrngState(v) { return Number.isSafeInteger(v) && v >= 0 && v <= 0xffffffff; }\nif (!validPrngState(state)) state = state >>> 0;","typeGuard":"const isPrngState = (v) => Number.isSafeInteger(v) && v >= 0 && v <= 0xffffffff;","tryCatchPattern":"try {\n  pet.random.restore(state);\n} catch (e) {\n  if (e.message === 'Invalid pet random stream.') pet.random.restore(seed);\n  else throw e;\n}","preventionTips":["Store PRNG state as a plain integer, not a float or string, when serializing checkpoints.","Apply `>>> 0` normalization at the save site so state is always a uint32.","Never restore state produced by a different PRNG implementation."],"tags":["rng","validation","checkpoint"],"backgroundTag":"value-out-of-range","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}