apache/echarts · error

Heatmap on cartesian must have two category axes

Error message

Heatmap on cartesian must have two category axes

What it means

DEV-only guard in HeatmapView rendering: when a heatmap is placed on a cartesian2d coordinate system, BOTH the x and y axes must be of type 'category'. A cartesian heatmap lays cells out on category bands, so value axes are unsupported there. Stripped in production.

Source

Thrown at src/chart/heatmap/HeatmapView.ts:185

        start: number,
        end: number,
        useIncremental?: boolean
    ) {
        const coordSys = seriesModel.coordinateSystem as Cartesian2D | Calendar | Matrix;
        const isCartesian2d = isCoordinateSystemType<Cartesian2D>(coordSys, 'cartesian2d');
        const isMatrix = isCoordinateSystemType<Matrix>(coordSys, 'matrix');
        let width;
        let height;
        let xAxisExtent;
        let yAxisExtent;

        if (isCartesian2d) {
            const xAxis = coordSys.getAxis('x');
            const yAxis = coordSys.getAxis('y');

            if (__DEV__) {
                if (!(xAxis.type === 'category' && yAxis.type === 'category')) {
                    throw new Error('Heatmap on cartesian must have two category axes');
                }
                if (!(xAxis.onBand && yAxis.onBand)) {
                    throw new Error('Heatmap on cartesian must have two axes with boundaryGap true');
                }
            }

            // add 0.5px to avoid the gaps
            width = calcBandWidth(xAxis).w + .5;
            height = calcBandWidth(yAxis).w + .5;
            xAxisExtent = xAxis.scale.getExtent();
            yAxisExtent = yAxis.scale.getExtent();
        }

        const group = this.group;
        const data = seriesModel.getData();

        let emphasisStyle = seriesModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
        let blurStyle = seriesModel.getModel(['blur', 'itemStyle']).getItemStyle();

View on GitHub (pinned to 30076aedcd)

Solutions

  1. Set xAxis.type='category' AND yAxis.type='category' on the grid the heatmap uses
  2. Supply matching category data arrays on both axes
  3. Use a different coordSys (calendar or matrix) if categories do not fit a grid

Example fix

// before
xAxis: { type: 'value' }, yAxis: { type: 'value' },
series: [{ type: 'heatmap', data: [...] }]

// after
xAxis: { type: 'category', data: hours },
yAxis: { type: 'category', data: days },
series: [{ type: 'heatmap', data: [...] }]
Defensive patterns

Strategy: validation

Validate before calling

const hm = (option.series || []).find((s: any) => s.type === 'heatmap');
if (hm && (hm.coordinateSystem == null || hm.coordinateSystem === 'cartesian2d')) {
  const xa = (option.xAxis && option.xAxis[0]) || {};
  const ya = (option.yAxis && option.yAxis[0]) || {};
  if (xa.type !== 'category' || ya.type !== 'category') {
    console.error('[heatmap] both cartesian axes must be category');
  }
}

Prevention

When it happens

Trigger: Heatmap series on a grid whose xAxis.type or yAxis.type is 'value' (the implicit default in some axis setups) instead of 'category'.

Common situations: Reusing a line/bar grid (value axes) for a heatmap; forgetting to set xAxis.type='category' on both axes; data-driven axis config that flips type.

Related errors


AI-assisted analysis of apache/echarts@30076aedcd (2026-08-12). Data as JSON: /api/errors/9fb6a7ddbf771102. Report an issue: GitHub.