koala73/worldmonitor · error · TypeError

Physical divergence snapshot must contain gold and silver re

Error message

Physical divergence snapshot must contain gold and silver readings

What it means

normalizePhysicalDivergenceSnapshot validates that a stored physical-divergence snapshot envelope contains exactly one reading per metal in PHYSICAL_DIVERGENCE_METALS (gold and silver, per the contract's metalOrder). It throws a TypeError when the readings array has the wrong length or contains duplicate/missing metals, because the stress composite cannot be computed from an incomplete or duplicated metal set. This is a data-integrity guard against corrupted or hand-edited snapshots.

Source

Thrown at server/_shared/physical-divergence-snapshot.ts:449

export function isUnsupportedPhysicalDivergenceMethodology(error: unknown): boolean {
  return error instanceof Error
    && error.message.startsWith('Unsupported physical divergence methodology:');
}

export function normalizePhysicalDivergenceSnapshot(
  value: unknown,
  nowMs = Date.now(),
): PhysicalDivergenceRawSnapshot {
  const raw = object(value);
  methodology(raw.methodologyVersion);
  if (!isoInstant(raw.evaluatedAt) || !Array.isArray(raw.readings) || !Array.isArray(raw.transitions)) {
    throw new TypeError('Physical divergence snapshot has an invalid envelope');
  }
  const storedReadings = raw.readings.map(reading);
  if (
    storedReadings.length !== PHYSICAL_DIVERGENCE_METALS.length
    || new Set(storedReadings.map((entry) => entry.metal)).size !== PHYSICAL_DIVERGENCE_METALS.length
  ) throw new TypeError('Physical divergence snapshot must contain gold and silver readings');
  validateStoredComposite(raw.composite, storedReadings);
  const readings = applyFreshness(storedReadings, nowMs);
  return {
    readings,
    composite: buildPhysicalStressComposite(readings),
    evaluatedAt: raw.evaluatedAt,
    methodologyVersion: PHYSICAL_DIVERGENCE_METHODOLOGY_VERSION,
    transitions: raw.transitions.map(transition),
  };
}

View on GitHub (pinned to 9361220cc0)

Solutions

  1. Re-seed or rewrite the snapshot so it contains exactly one reading for each metal in PHYSICAL_DIVERGENCE_METALS (gold and silver)
  2. Check the writer that produced the snapshot: it must emit one reading per contract metal, using the canonical metal identifiers
  3. Check for schema drift: if PHYSICAL_DIVERGENCE_METALS changed (contract metalOrder), regenerate all stored snapshots to match
  4. Validate the raw payload with the same length/distinct-metal check before persisting it

Example fix

// before
readings: [{ metal: 'gold', price: 2300 }]
// after
readings: [
  { metal: 'gold', ... },
  { metal: 'silver', ... }
]
Defensive patterns

Strategy: validation

Validate before calling

function isValidSnapshotReadings(readings) {
  return Array.isArray(readings)
    && readings.length === PHYSICAL_DIVERGENCE_METALS.length
    && new Set(readings.map((r) => r.metal)).size === PHYSICAL_DIVERGENCE_METALS.length;
}
// run before normalizePhysicalDivergenceSnapshot on any stored payload

Type guard

function hasAllMetals(readings): readings is PhysicalDivergenceReading[] {
  return Array.isArray(readings)
    && PHYSICAL_DIVERGENCE_METALS.every((m) => readings.some((r) => r?.metal === m));
}

Try / catch

try {
  const snap = normalizePhysicalDivergenceSnapshot(raw, nowMs);
} catch (e) {
  if (e instanceof TypeError && /gold and silver/.test(e.message)) {
    snap = await reseedSnapshot(); // regenerate from source
  } else throw e;
}

Prevention

When it happens

Trigger: raw.readings maps to fewer entries than PHYSICAL_DIVERGENCE_METALS.length, or two readings carry the same metal value (e.g. both 'gold'), or a reading's metal field was dropped/renamed during serialization so the distinct-metal count mismatches.

Common situations: A Redis snapshot written by an older schema version missing one metal; a manual seed edit that duplicated gold and omitted silver; a migration or copy/paste that truncated the readings array; an upstream writer bug that serializes metals with different casing or keys.

Related errors


AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01). Data as JSON: /api/errors/0ea0802319ecf383. Report an issue: GitHub.