Stirling-Tools/Stirling-PDF · error · Error

Unsupported unit: ${unit}

Error message

Unsupported unit: ${unit}

What it means

Thrown by calculateScaleFactor after normalizeUnit(unit) (lowercase + trim) is not a key of POINT_TO_UNIT. Supported units are exactly m, cm, mm, km, ft, in, yd, mi. Any other string (including 'inch', 'meter', 'pixel', or whitespace variants not collapsed by trim) triggers it.

Source

Thrown at frontend/editor/src/core/utils/measurementUtils.ts:51

  return Object.hasOwn(POINT_TO_UNIT, unit);
}

export function getUnitFactor(unit: string): number | undefined {
  const normalized = normalizeUnit(unit);
  if (!isMeasurementUnit(normalized)) {
    return undefined;
  }
  return POINT_TO_UNIT[normalized];
}

export function calculateScaleFactor(ratio: number, unit: string): number {
  if (!Number.isFinite(ratio) || ratio <= 0) {
    throw new Error(`Invalid scale ratio: ${ratio}`);
  }

  const normalized = normalizeUnit(unit);
  if (!isMeasurementUnit(normalized)) {
    throw new Error(`Unsupported unit: ${unit}`);
  }

  return POINT_TO_UNIT[normalized] * ratio;
}

export function generateScaleLabel(ratio: number | null, unit: string): string {
  if (ratio === null || ratio === undefined) {
    return unit;
  }
  const display = Number.isInteger(ratio)
    ? ratio.toString()
    : ratio.toFixed(2).replace(/\.?0+$/, "");
  return `1:${display} (${unit})`;
}

// Imperial units
const IMPERIAL_UNITS = ["ft", "in", "yd", "mi"] as const;
export function isImperialUnit(unit: string): boolean {

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Always pass canonical unit codes (m, cm, mm, km, ft, in, yd, mi) — keep display labels separate from stored values.
  2. Call getUnitFactor(unit) first; if it returns undefined, surface a friendly error before hitting calculateScaleFactor.
  3. Add a unit picker UI constrained to the known MeasurementUnit type so free text never reaches the function.
  4. Extend normalizeUnit to handle common aliases if you control the inputs.

Example fix

// before
calculateScaleFactor(ratio, userTypedUnit);

// after
const validUnits = ["m", "cm", "mm", "km", "ft", "in", "yd", "mi"] as const;
if (!validUnits.includes(userTypedUnit.toLowerCase().trim() as never)) {
  throw new Error(`Unknown unit "${userTypedUnit}". Use one of: ${validUnits.join(", ")}`);
}
calculateScaleFactor(ratio, userTypedUnit);
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED_UNITS = Object.keys(POINT_TO_UNIT);
if (!SUPPORTED_UNITS.includes(unit.toLowerCase().trim())) {
  throw new Error(`Unsupported unit "${unit}". Use: ${SUPPORTED_UNITS.join(", ")}`);
}
calculateScaleFactor(ratio, unit);

Type guard

function isMeasurementUnit(unit: string): unit is MeasurementUnit {
  return Object.hasOwn(POINT_TO_UNIT, unit.toLowerCase().trim());
}

Prevention

When it happens

Trigger: Calling calculateScaleFactor(1, 'inch'); passing a localized full unit name ('centimeters'); a unit pulled from a persisted config that was saved with an unexpected token; trailing/internal whitespace normalizeUnit does not collapse (e.g. 'c m').

Common situations: i18n: storing display labels instead of canonical unit codes; migrating from an older unit list; third-party plugin reusing the helper with its own unit vocabulary.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/02031a97d4e82056. Report an issue: GitHub.