Toolarity

Grafana Value Mapping Not Working? 9 Rules I Tested

Fix Grafana Published October 3, 2026

A value mapping in Grafana turns a number or a string into text and a color: 1 → UP in green, 0 → DOWN in red. When it doesn’t work, Grafana shows no error. The panel just shows the raw value, the wrong text, or the right text in the wrong color.

I built a test dashboard with 33 Stat and Table panels on Grafana 13.2.3 (the current release when I tested, 2026-09-30). Each panel reads a small CSV from the built-in TestData data source and changes one mapping setting. The screenshots show the panel title, which names the setting, and what the panel displayed.

Short answer (Grafana 13.2.3, tested 2026-09-30):

What you seeCauseFix
Two mappings match, the wrong one winsMappings are checked top to bottom; the first match winsDrag the mapping you want to the top
A range boundary lands in the wrong rangeBoth ends of a range are inclusiveMake ranges not touch, e.g. 0–9.99 and 10–20
Regex mapping never matchesWithout /…/, the pattern must match the whole valueMatch the whole value, or write /pattern/
Regex mapping ignored on numbersRegex mappings only look at stringsUse a Value or Range mapping
Mapping color not shownColor mode is None, or a Table cell type is AutoStat: Color mode Value or Background. Table: cell type Color text or Color background
Text is right, color is the threshold colorThe mapping has no color of its ownSet a color on the mapping
Null mapping never firesCalculation is Last *, which skips nullsUse Last if you want to see the null
${var} shows up literallyDashboard variables aren’t replaced in mappingsNot possible with value mappings
Value 1 not mappedThe mapping key is 1.0Type the value exactly as Grafana shows it

1. The first matching mapping wins

Grafana 13.2.3, two tables with the values -1, 0, 9.99, 10, 10.01, 20, 21 in rows a to g. Top, range 0-10 LOW listed before 10-20 MID: -1, LOW, LOW, LOW, MID, MID, 21. Bottom, MID listed first: -1, LOW, LOW, MID, MID, MID, 21.

Two range mappings, 0 to 10 → LOW and 10 to 20 → MID, and the values −1, 0, 9.99, 10, 10.01, 20 and 21 (rows a to g):

  • Both ends are inclusive. 0 became LOW, 20 became MID.
  • 10 is in both ranges, so the order decides. With LOW listed first, 10 was LOW (top). With MID first, 10 was MID (bottom).
  • Values outside every range (−1 and 21) are shown as they are.

The same rule applies across mapping types. A Value mapping does not win over a Range mapping just because it’s more specific:

Grafana 13.2.3. Value 5 with a value mapping 5 to EXACT and a range mapping 0-10 to LOW. Value mapping listed first: EXACT. Range mapping listed first: LOW.

The value 5 matched both 5 → EXACT and 0–10 → LOW. Whichever was listed first won.

A range with only From set (From 10, To empty) worked as “10 or more”: 5 stayed 5, while 10 and 1000 both became >=10.

The docs (Configure value mappings, read 2026-09-30) don’t mention the order or the inclusive ends. The source does. In Grafana v13.2.3, getValueMappingResult() in packages/grafana-data/src/utils/valueMappings.ts loops over the mappings in order, returns the first result it finds, and skips a range only when the value is < from or > to.

Fix: reorder the mappings in the editor so the one you want is on top, or make ranges not touch (0–9.99 and 10–20).

2. Regex mappings: whole string, strings only

Grafana 13.2.3, a host column with web-01, myweb-02, WEB-03, db-01. Regex web-(.) to $1: 01, myweb-02, WEB-03, db-01. Regex /web-(.)/i to $1: 01, my02, 03, db-01. Regex web to W: nothing changes.

The data: web-01, myweb-02, WEB-03, db-01.

Pattern → textResult
web-(.*) → $101, myweb-02, WEB-03, db-01
^web-(.*)$ → Web $1Web 01, myweb-02, WEB-03, db-01
/web-(.*)/i → $101, my02, 03, db-01
web → Wnothing changed
  • Without slashes, the pattern has to match the whole value. web-(.*) gave the same matches as ^web-(.*)$. It didn’t match myweb-02, and web alone matched nothing at all.
  • With slashes, it’s a normal JavaScript regex. /web-(.*)/i matched part of myweb-02 and replaced only that part, giving my02. The i flag made WEB-03 match too.

The value mappings docs don’t state the whole-value rule. In the source, the regex mapping calls stringToJsRegex() (packages/grafana-data/src/text/string.ts), which wraps a pattern without slashes as ^pattern$.

Regex mappings ignore numbers. On a number column with 1, 10 and 21, the mapping 1(.*) → one$1 changed nothing, not even 1 and 10, which match that pattern as a whole. The source skips any value that isn’t a string. For numbers, use a Value or Range mapping.

3. Colors: when the mapping color shows up

Grafana 13.2.3 Stat panels, all showing UP for the value 1. Mapping color green with Color mode None: gray-white UP. Mapping without a color and a red base threshold: red UP. Mapping color green with color scheme Single color blue: green UP.

On a Stat panel, the mapping text UP had a green color set:

  • Color mode Value: green text. Background: green background, white text.
  • Color mode None: gray-white text. The mapping color is ignored (top).
  • The mapping has no color: the text took the threshold color, red in my test (middle). A mapping without a color doesn’t mean “no color”.
  • Color scheme Single color (blue): the mapping’s green still won (bottom).

In a table, colors depend on the cell type:

Grafana 13.2.3 tables with web-01 UP and web-02 DOWN. Cell type Auto: plain text, no color. Cell type Color text: UP green, DOWN red. Cell type Color background: green and red cells.

With the cell type on Auto, the text was mapped but had no color. Color text and Color background showed the mapping colors. The docs say this too, in their table example.

4. Null, NaN and “No value”

This is where the calculation matters more than the mapping.

Grafana 13.2.3 Stat panels with the values 5 and then an empty last row, and a special mapping Null to N/A in orange. Calculation Last *: 5. Calculation Last: N/A in orange.

The data had two rows: 5, then an empty value. With a Special → Null mapping to N/A:

  • Calculation Last * (last non-null) showed 5. It skips the null, so the null mapping never gets a null to map (top).
  • Calculation Last showed N/A in orange (bottom).

More results from the same kind of panels:

DataSettingsShown
Every value emptyLast *, Null → N/AN/A
Every value emptyLast *, No value nothing, Null → N/AN/A: the null mapping won over No value
CSV header only, no rowsNull → N/AN/A
CSV header only, no rowsNo value nothing, no mappingnothing
Last value NaNLast, NaN → not a numbernot a number
Last value emptyLast, Null + NaN → N/A, no colorN/A in the default text color

So if you set both No value and a Null mapping, you’ll see the mapping’s text. Pick one.

Empty (empty string) mappings: not tested in this batch. TestData reads an empty CSV cell as null, not as an empty string. In my table test, empty cells showed the Null mapping’s text, and a table with only an Empty mapping left the cell blank. That tells you about TestData, not about the Empty mapping. To test Empty you need a data source that really returns "".

5. Dashboard variables are not replaced

Grafana 13.2.3 Stat panels. Mapping key 1.0 with the value 1: shows 1, not mapped. Mapping 1 to UP with unit percent: shows UP without a percent sign. Mapping 1 to ${env} up: shows the literal text ${env} up.

The dashboard had a variable env set to prod. A mapping 1 → ${env} up showed ${env} up, literally (bottom). A mapping whose key was ${one}, with the variable one set to 1, didn’t match the value 1 at all.

Value mappings didn’t replace dashboard variables, in the text or in the key.

6. Two smaller ones

  • 1.0 is not 1. A Value mapping with the key 1.0 didn’t match the value 1 (top of the screenshot above). The key is compared as text. 0 as a key worked fine for the value 0.
  • Mapped text has no unit. With the unit set to Percent, the mapped value showed UP, not UP %. The docs say this: value mappings “bypass unit formatting”.

What I’d do

  • Put the most specific mapping first, and don’t let ranges share a boundary.
  • Write regex patterns for the whole value, like web-.*, or use /…/ when you want to match part of it.
  • Give every mapping a color, or you get the threshold color.
  • Decide between Last and Last * before you add a Null mapping. With Last *, the Null mapping only fires when there are no non-null values at all.

What this test does not cover

  • Only Grafana OSS 13.2.3 in Docker, tested 2026-09-30, with the TestData data source (CSV content). I built the panels from dashboard JSON through the Grafana HTTP API and checked the rendered panels.
  • Not tested in this batch: Empty (empty string) mappings, see above.
  • Stat and Table panels only. Time series, bar gauge, state timeline and canvas can treat mapping colors differently; the docs say time series doesn’t use them.
  • Boolean (true/false) special mappings.
  • Grafana Cloud and older self-hosted versions.