Hmbown/CodeWhale · error · Error

Invalid recording archive.

Error message

Invalid recording archive.

What it means

petArchive(key) validates that the requested archive key is a safe positive integer before looking up the IndexedDB habitat store. It throws this Error when the key argument itself is malformed; a well-formed but absent key produces the distinct 'This recording is unavailable.' error instead.

Solutions

  1. Coerce and validate the key with Number before calling: const k = Number(raw); if (!Number.isSafeInteger(k) || k < 1) ...
  2. Guard the call site to only pass keys that came from a listed PetArchive record.
  3. Handle the thrown error in the UI to show an invalid-link message.

Example fix

// before
await store.petArchive(params.id);
// after
const key = Number(params.id);
if (!Number.isSafeInteger(key) || key < 1) return showError('Invalid archive id');
await store.petArchive(key);
Defensive patterns

Strategy: validation

Validate before calling

function isValidArchiveKey(key) { return Number.isSafeInteger(key) && key >= 1; }
if (!isValidArchiveKey(key)) throw new RangeError('archive key must be a positive safe integer');

Type guard

const isValidArchiveKey = (k: unknown): k is number => typeof k === 'number' && Number.isSafeInteger(k) && k >= 1;

Prevention

When it happens

Trigger: Calling petArchive(0), petArchive(-5), petArchive(1.5), petArchive(2**53), or petArchive(NaN) — any key failing Number.isSafeInteger(key) || key >= 1.

Common situations: Parsing an id from a URL query string without Number conversion, passing undefined/null from an unverified record field, or deserializing a corrupted archive reference.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at pet/src/ui/storage.ts:167

        }
        const revision = (previous?.revision ?? 0) + 1;
        if (archive) {
          habitats.add(archive, `pet-archive-${revision}`);
          habitats.add({ key: revision, name: archive.sourceName, seconds: archive.seconds,
            startSeconds: (archive.start?.frame.timeMs ?? 0) / 1000 }, `pet-archive-meta-${revision}`);
        }
        habitats.put({ revision, habitat }, 'pet'); done(revision);
      };
    });
  }
  async petArchives(): Promise<PetArchive[]> {
    return this.transaction('readonly', (_traces, _metas, done, _fail, habitats) => {
      const request = habitats.getAll(IDBKeyRange.bound('pet-archive-meta-', 'pet-archive-meta-\uffff'));
      request.onsuccess = () => done((request.result as PetArchive[]).sort((a, b) => b.key - a.key));
    });
  }
  async petArchive(key: number): Promise<SavedHabitat> {
    if (!Number.isSafeInteger(key) || key < 1) throw new Error('Invalid recording archive.');
    return this.transaction('readonly', (_traces, _metas, done, fail, habitats) => {
      const request = habitats.get(`pet-archive-${key}`);
      request.onsuccess = () => request.result ? done(request.result) : fail(new Error('This recording is unavailable.'));
    });
  }
}

View on GitHub (pinned to 433685b202)