koala73/worldmonitor · error · ValidationError

Unsupported metal${unsupported.length === 1 ? '' : 's'}: ${u

Error message

Unsupported metal${unsupported.length === 1 ? '' : 's'}: ${unsupported.join(', ')}

What it means

Validation in resolvePhysicalPremiumMetals: one or more requested metals (listed in the message) are not in SUPPORTED_METALS after trim and lowercase normalization — including blank entries, reported as '<blank>'. The whole request is rejected rather than silently dropping the unsupported metals.

Source

Thrown at server/worldmonitor/market/v1/get-physical-premiums.ts:159

    || !isoInstant(raw.asOf)
  ) return null;
  return { pair: raw.pair, rate: raw.rate, source: raw.source, asOf: raw.asOf };
}

export function resolvePhysicalPremiumMetals(rawMetals: string[]): string[] {
  const metals: string[] = [];
  const unsupported: string[] = [];
  for (const raw of rawMetals) {
    const metal = raw.trim().toLowerCase();
    if (!metal || !SUPPORTED_METALS.has(metal)) {
      const label = metal || '<blank>';
      if (!unsupported.includes(label)) unsupported.push(label);
      continue;
    }
    if (!metals.includes(metal)) metals.push(metal);
  }
  if (unsupported.length > 0) {
    throw new ValidationError([{
      field: 'metals',
      description: `Unsupported metal${unsupported.length === 1 ? '' : 's'}: ${unsupported.join(', ')}`,
    }]);
  }
  return metals;
}

export async function getPhysicalPremiums(
  _ctx: ServerContext,
  req: GetPhysicalPremiumsRequest,
): Promise<GetPhysicalPremiumsResponse> {
  const metals = resolvePhysicalPremiumMetals(parseStringArray(req.metals));
  try {
    const raw = await getCachedJson(PHYSICAL_PREMIUM_KEY, true) as RawPayload | null;
    const fx = mapFx(raw?.fx);
    if (!fx || !Array.isArray(raw?.premiums)) return { premiums: [] };
    const premiums = raw.premiums.map((premium) => mapPremium(premium, fx.rate))
      .filter((item): item is PhysicalPremium => item !== null);

View on GitHub (pinned to eeab0a219f)

Solutions

  1. Request only supported metals; check the message for the exact unsupported labels
  2. Trim and validate the metals list client-side against the supported set before calling
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/worldmonitor/market/v1/get-physical-premiums.ts:159 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21). Data as JSON: /api/errors/9f8e48d16bc4252e. Report an issue: GitHub.