ant-design/ant-design · error · Error

${screenMax}<=${nextScreenMin} fails : !(${indexableToken[sc

Error message

${screenMax}<=${nextScreenMin} fails : !(${indexableToken[screenMax]}<=${indexableToken[nextScreenMin]})

What it means

validateBreakpoints() asserts that consecutive breakpoints chain correctly: screenXXMax <= nextScreenYYMin, where 'next' is the next entry in the reversed breakpoint array (i.e. the next smaller breakpoint). By default screenXXMax = nextScreen - 1 and nextScreenMin = nextScreen, so the invariant holds (575 <= 576). This is the third check in the loop (line 58), skipped for the last breakpoint. When it fails, one breakpoint's ceiling overlaps or exceeds the next breakpoint's floor, creating a gap or contradiction in the media-query lattice that responsive observers depend on.

Source

Thrown at components/_util/responsiveObserver.ts:59

      throw new Error(
        `${screenMin}<=${screen} fails : !(${indexableToken[screenMin]}<=${indexableToken[screen]})`,
      );
    }

    if (i < revBreakpoints.length - 1) {
      const screenMax = `screen${breakpointUpper}Max`;

      if (!(indexableToken[screen] <= indexableToken[screenMax])) {
        throw new Error(
          `${screen}<=${screenMax} fails : !(${indexableToken[screen]}<=${indexableToken[screenMax]})`,
        );
      }

      const nextBreakpointUpperMin = revBreakpoints[i + 1].toUpperCase();
      const nextScreenMin = `screen${nextBreakpointUpperMin}Min`;

      if (!(indexableToken[screenMax] <= indexableToken[nextScreenMin])) {
        throw new Error(
          `${screenMax}<=${nextScreenMin} fails : !(${indexableToken[screenMax]}<=${indexableToken[nextScreenMin]})`,
        );
      }
    }
  });
  return token;
};

export const matchScreen = (screens: ScreenMap, screenSizes?: ScreenSizeMap) => {
  if (!screenSizes) {
    return;
  }
  for (const breakpoint of responsiveArray) {
    if (screens[breakpoint] && screenSizes?.[breakpoint] !== undefined) {
      return screenSizes[breakpoint];
    }
  }
};

View on GitHub (pinned to 6455d91fab)

Solutions

  1. Read the error message for the exact pair, e.g. screenXSMax<=screenSMMin fails : !(1010<=576). Raise the second token (nextScreenMin) above the first (screenMax), or lower screenMax.
  2. When you increase screenXXMax, also increase the next breakpoint's screenYY / screenYYMin so that screenXXMax < screenYYMin.
  3. Override breakpoint tiers in contiguous groups rather than one tier at a time, so every boundary is consistent.
  4. Validate the full chain xs→xxxl before passing tokens to ConfigProvider: screenXSMax < screenSMMin, screenSMMax < screenMDMin, and so on for all six boundaries.

Example fix

// before — screenXSMax (1010) exceeds screenSMMin (576)
<ConfigProvider theme={{ token: { screenXS: 1000, screenXSMin: 1000, screenXSMax: 1010 } }}>
  <App />
</ConfigProvider>

// after — raise the adjacent breakpoint to preserve the chain
<ConfigProvider theme={{ token: { screenXS: 1000, screenXSMin: 1000, screenXSMax: 1010, screenSM: 1024, screenSMMin: 1024 } }}>
  <App />
</ConfigProvider>
Defensive patterns

Strategy: validation

Validate before calling

import { responsiveArray } from 'antd/es/_util/responsiveObserver';

// Call before passing tokens to ConfigProvider
function assertBreakpointChainValid(token: Record<string, any>): void {
  const rev = [...responsiveArray].reverse(); // xxxl, xxl, xl, lg, md, sm, xs
  for (let i = 0; i < rev.length - 1; i++) {
    const upper = rev[i].toUpperCase();
    const nextUpper = rev[i + 1].toUpperCase();
    const max = token[`screen${upper}Max`];
    const nextMin = token[`screen${nextUpper}Min`];
    if (typeof max === 'number' && typeof nextMin === 'number' && max > nextMin) {
      throw new Error(
        `Invalid token chain: screen${upper}Max (${max}) > screen${nextUpper}Min (${nextMin}). Raise the next breakpoint or lower screen${upper}Max.`,
      );
    }
  }
}

// Usage:
// const myToken = { screenXS: 1000, screenXSMin: 1000, screenXSMax: 1010, screenSM: 1024, screenSMMin: 1024 };
// assertBreakpointChainValid(myToken);
// <ConfigProvider theme={{ token: myToken }}>...

Type guard

import type { AliasToken } from 'antd/es/theme/interface/alias';
import { responsiveArray } from 'antd/es/_util/responsiveObserver';

function hasValidBreakpointChain(token: Partial<AliasToken>): boolean {
  const rev = [...responsiveArray].reverse();
  for (let i = 0; i < rev.length - 1; i++) {
    const upper = rev[i].toUpperCase();
    const nextUpper = rev[i + 1].toUpperCase();
    const max = token[`screen${upper}Max` as keyof AliasToken] as number | undefined;
    const nextMin = token[`screen${nextUpper}Min` as keyof AliasToken] as number | undefined;
    if (max === undefined || nextMin === undefined) continue;
    if (max > nextMin) return false;
  }
  return true;
}

Try / catch

// Throws during React render — wrap in an Error Boundary, not a try/catch:
import React from 'react';

class BreakpointErrorBoundary extends React.Component<
  { children: React.ReactNode; fallback?: React.ReactNode },
  { hasError: boolean }
> {
  state = { hasError: false };
  static getDerivedStateFromError() {
    return { hasError: true };
  }
  componentDidCatch(err: Error) {
    if (err.message.includes('fails : !(')) {
      console.error('Breakpoint chain validation failed:', err.message);
    }
  }
  render() {
    return this.state.hasError ? (this.props.fallback ?? null) : this.props.children;
  }
}
// This only masks the crash; the responsive component will not render until
// the token chain is fixed.

Prevention

When it happens

Trigger: Fires when a ConfigProvider theme.token override makes screenXXMax > nextScreenYYMin. Typical: { screenXS: 1000, screenXSMin: 1000, screenXSMax: 1010 } where screenSMMin stays at 576, producing screenXSMax<=screenSMMin fails : !(1010<=576). Also triggers when increasing any screenXXMax beyond the next breakpoint's Min without also raising that next breakpoint.

Common situations: Occurs when a developer overrides one breakpoint's Max (or all three values of one tier) but leaves adjacent breakpoints at defaults — the raised ceiling spills past the neighbor's floor. Also seen when porting a design-system spec that defines non-contiguous or overlapping breakpoints, or when incrementally adding token overrides without re-checking the full chain after each addition.

Related errors


AI-assisted analysis of ant-design/ant-design@6455d91fab (2026-08-12). Data as JSON: /api/errors/df8a76156f54d385. Report an issue: GitHub.