date-fns/date-fns · error · RangeError

The format string mustn't contain `${token}` and any other t

Error message

The format string mustn't contain `${token}` and any other token at the same time

What it means

parse() at parse/index.ts:447-450 handles parsers whose incompatibleTokens === '*', meaning they cannot coexist with ANY other token in the same format string (e.g. the localized 'P'/'p' long-form tokens, or the standalone 'p' time-only token). If usedTokens already has anything when such a token is reached, parse throws RangeError naming the all-incompatible token.

Source

Thrown at pkgs/core/src/parse/index.ts:448

    }

    const firstCharacter = token[0];
    const parser = parsers[firstCharacter];
    if (parser) {
      const { incompatibleTokens } = parser;
      if (Array.isArray(incompatibleTokens)) {
        const incompatibleToken = usedTokens.find(
          (usedToken) =>
            incompatibleTokens.includes(usedToken.token) ||
            usedToken.token === firstCharacter,
        );
        if (incompatibleToken) {
          throw new RangeError(
            `The format string mustn't contain \`${incompatibleToken.fullToken}\` and \`${token}\` at the same time`,
          );
        }
      } else if (parser.incompatibleTokens === "*" && usedTokens.length > 0) {
        throw new RangeError(
          `The format string mustn't contain \`${token}\` and any other token at the same time`,
        );
      }

      usedTokens.push({ token: firstCharacter, fullToken: token });

      const parseResult = parser.run(
        dateStr,
        token,
        locale.match,
        subFnOptions,
      );

      if (!parseResult) {
        return invalidDate();
      }

      setters.push(parseResult.setter);

View on GitHub (pinned to 4098115cf7)

Solutions

  1. Use a fully explicit format string ('yyyy-MM-dd HH:mm') instead of mixing 'P' or 'p' with other tokens.
  2. If you need localized date+time, use a single locale-aware pattern (the locale's formatLong.date + ' ' + formatLong.time) or call parse twice.
  3. Check the parser's incompatibleTokens value (look for '*' in pkgs/core/src/_lib/parse) when in doubt.

Example fix

// before
parse(input, 'P p', referenceDate)
// after
parse(input, 'yyyy-MM-dd HH:mm:ss', referenceDate)
Defensive patterns

Strategy: validation

Validate before calling

// '*'-incompatible tokens cannot share a format with anything else.
const STAR_INCOMPATIBLE = new Set(['P','p','Q','q'])
function assertNoMixedStarToken(fmt: string) {
  const re = /(\w)\1*|''|'(''|[^'])+('|$)|./g
  const toks = (fmt.match(re) ?? []).filter(t => /[a-zA-Z]/.test(t[0]))
  const star = toks.find(t => STAR_INCOMPATIBLE.has(t[0]))
  if (star && toks.length > 1) throw new Error(`Token ${star} cannot mix with others`)
}

Try / catch

try { return parse(s, fmt, ref) }
catch (e) { if (e instanceof RangeError && /and any other token at the same time/.test(e.message)) return new Date(NaN); throw e }

Prevention

When it happens

Trigger: parse(s, 'P yyyy', ...) mixes the localized long-date 'P' with a calendar-year 'y'; parse(s, 'pp HH:mm', ...) mixes two time-only patterns; any format that combines a '*'-incompatible token with another token.

Common situations: Concatenating a localized 'P' pattern with extra tokens to add a time component; copy-pasting a locale-aware format string and tacking on more tokens; mismatched expectations from Moment.js migration.

Related errors


AI-assisted analysis of date-fns/date-fns@4098115cf7 (2026-08-03). Data as JSON: /data/errors/dc191eb798b33704.json. Report an issue: GitHub.