{"record":{"id":"2565ffc4792962d8","repo":"thingsboard/thingsboard","slug":"unsupported-unit-from","errorCode":null,"errorMessage":"Unsupported unit: ${from}","messagePattern":"Unsupported unit: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ui-ngx/src/app/shared/models/unit.models.ts","lineNumber":456,"sourceCode":"\n  constructor(\n    measures: Record<AllMeasures, TbMeasure<AllMeasuresUnits>>,\n    unitCache: UnitCache\n  ) {\n    this.measureData = measures;\n    this.unitCache = unitCache;\n  }\n\n  getUnitConverter(from: AllMeasuresUnits | string, to: AllMeasuresUnits | string): TbUnitConverter {\n    return (value: number) => this.convert(value, from, to);\n  }\n\n  convert(value: number, from: AllMeasuresUnits | string, to: AllMeasuresUnits | string): number {\n    const origin = this.getUnit(from);\n    const destination = this.getUnit(to);\n\n    if (!origin) {\n      throw new Error(`Unsupported unit: ${from}`);\n    }\n    if (!destination) {\n      throw new Error(`Unsupported unit: ${to}`);\n    }\n    if (origin.abbr === destination.abbr) {\n      return value;\n    }\n    if (destination.measure !== origin.measure) {\n      throw Error(`Cannot convert incompatible measures: ${origin.measure} to ${destination.measure}`);\n    }\n    let result = value * origin.unit.to_anchor;\n    if (origin.unit.anchor_shift) {\n      result -= origin.unit.anchor_shift;\n    }\n    if (typeof origin.unit.transform === 'function') {\n      result = origin.unit.transform(result);\n    }\n    if (origin.system !== destination.system) {","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/thingsboard/thingsboard/blob/45c30e83fa57356840d5f25d894002d94222d524/ui-ngx/src/app/shared/models/unit.models.ts#L438-L474","documentation":"Thrown by ThingsBoard's unit conversion service (unit.models.ts) when the source ('from') unit cannot be resolved by getUnit(). Units are looked up against the convert-units measure definitions; an unknown abbreviation/name yields a falsy origin and this Error. It usually surfaces from widget/legend unit conversion on dashboards.","triggerScenarios":"Calling convert()/getUnitConverter() with a 'from' string not present in the unit registry: a typo like 'Celcius', a localized unit symbol, an empty string, or a custom unit abbreviation never registered via UnitSetConfigurator.","commonSituations":"Dashboard widget datasource or legend configured with a custom/misspelled unit; data from devices sending unusual unit strings; upgrading ThingsBoard where supported unit lists changed; telemetry unit metadata containing '%' or '' handled as convertible units.","solutions":["Check the exact 'from' string against supported values (see AllMeasuresUnits in unit.models.ts / the convert-units library measures).","Fix typos or use the canonical abbreviation (e.g. 'C' not '°C', 'kWh' not 'kWH').","If it is a custom unit, register it via the UnitSetConfigurator/units extension point before converting.","Skip conversion entirely when from === to or when the unit is unknown to the registry."],"exampleFix":"// before\nconst c = unitsService.getUnitConverter(widgetUnit, targetUnit);\nc(value);\n\n// after: verify unit exists before converting\nconst origin = unitsService.getUnit(widgetUnit);\nif (!origin) { return value; } // or skip conversion in widget settings\nconst c = unitsService.getUnitConverter(widgetUnit, targetUnit);","handlingStrategy":"validation","validationCode":"// before building a converter\nif (!unitsService.getUnit(fromUnit)) {\n  // skip conversion, log unit string, keep raw value\n  return of(rawValue);\n}\nconst convert = unitsService.getUnitConverter(fromUnit, toUnit);","typeGuard":"function isSupportedUnit(u: string): boolean {\n  return unitsService.getUnit(u) != null;\n}","tryCatchPattern":"try {\n  result = unitsService.convert(value, from, to);\n} catch (e: any) {\n  if (e instanceof Error && e.message.startsWith('Unsupported unit')) {\n    // fall back to raw value and surface a config warning\n    result = value;\n  } else { throw e; }\n}","preventionTips":["Use AllMeasuresUnits enum values instead of free-text unit strings.","Validate dashboard JSON unit settings before import.","Treat unknown units as pass-through rather than converting."],"tags":["angular","units","conversion","dashboard"],"backgroundTag":null,"analyzedSha":"45c30e83fa57356840d5f25d894002d94222d524","analyzedAt":"2026-08-14T11:45:36.599Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}