← Back to Blog

Fix 'version solving failed': flutter_localizations & intl

intlflutter_localizationspubdependency conflictl10nflutter upgrade

Fix 'version solving failed': flutter_localizations & intl

You upgraded Flutter (or added a package), ran flutter pub get, and hit this:

Because every version of flutter_localizations from sdk depends on intl 0.19.0
and myapp depends on intl ^0.20.2, flutter_localizations from sdk is forbidden.
So, because myapp depends on flutter_localizations from sdk, version solving failed.

This is one of the most common Flutter i18n errors, and the fix is usually a one-liner — but which one-liner depends on where the conflict comes from. This post explains why the SDK hard-pins intl, then walks a decision tree with a copy-paste fix for each scenario.

Why flutter_localizations hard-pins intl

Unlike normal pub packages, flutter_localizations ships inside the Flutter SDK. It isn't resolved from pub.dev; it comes from whatever Flutter version you have installed, and its pubspec.yaml declares an exact dependency on intl — no caret, no range:

Flutter version intl constraint in flutter_localizations
3.19 – 3.29 intl: 0.19.0 (exact)
3.32 – current stable intl: 0.20.2 (exact)
master (future stable) intl: ^0.20.3 (finally a range)

The pin exists because flutter_localizations contains generated localized strings and date/number formatting behavior for Material and Cupertino widgets that are built and tested against one specific snapshot of intl's CLDR locale data. An exact pin guarantees the framework's own date pickers, calendars, and formatted strings behave exactly as tested. The cost is that your whole app is locked to that one intl version — pub's version solver has no room to negotiate.

That's why the error says flutter_localizations intl 0.19.0 forbidden-style things: the solver isn't confused, it's correctly reporting that your constraint (^0.20.2) and the SDK's pin (0.19.0) have an empty intersection.

Good news: the Flutter team has relaxed the pin to a caret range (^0.20.3) on master, so this class of conflict will get rarer in future releases. Until that reaches your stable version, here's how to fix it today.

First: find out what your SDK actually pins

grep -A1 '  intl' "$(dirname "$(which flutter)")/../packages/flutter_localizations/pubspec.yaml"

Or just read the error message — pub prints the pinned version verbatim.

The decision tree

Scenario 1: Your own pubspec.yaml constrains intl → use intl: any

If your app declares something like intl: ^0.20.2 and the conflict names your app directly (like the error above), the officially recommended fix is to let the SDK decide:

flutter pub add intl:any

This rewrites your pubspec to:

dependencies:
  flutter_localizations:
    sdk: flutter
  intl: any

any looks scary but is safe here: because flutter_localizations exact-pins intl, the solver has exactly one version it can pick — the pinned one. You still get a real, locked version in pubspec.lock, and it automatically follows the pin whenever you upgrade Flutter. This is what the official internationalization docs recommend, and it permanently ends the tug-of-war between your constraint and the SDK's.

The trade-off: you can't force a newer intl than the SDK ships. If you specifically need an intl 0.20-only capability (Dart 3.3+, WASM compilation support, newer CLDR data, typed numberFormatSymbols), go to Scenario 2.

Scenario 2: You need a newer intl than your SDK allows → upgrade Flutter

If you're on Flutter 3.29 or older, the SDK pins intl 0.19.0 and nothing in your pubspec can change that. The pin only moves when Flutter moves — it jumped to 0.20.2 in Flutter 3.32 (May 2025). So to upgrade the intl package in Flutter, upgrade Flutter itself:

flutter upgrade
flutter --version   # confirm 3.32 or later
flutter clean
flutter pub get

If your pubspec uses intl: any (Scenario 1), the resolved intl version moves up automatically with the new pin — no pubspec edit needed. Check what you got:

grep -A2 '^  intl:' pubspec.lock

Scenario 3: A transitive dependency causes the conflict → upgrade it, or override as a last resort

Sometimes you never touched intl — a package you depend on did:

Because stale_charts >=1.2.0 depends on intl ^0.19.0 and every version of
flutter_localizations from sdk depends on intl 0.20.2, stale_charts >=1.2.0
is incompatible with flutter_localizations from sdk.

Try the clean fixes first:

# 1. See who drags in which intl
flutter pub deps --style=compact | grep intl

# 2. A newer release of the package may already allow intl 0.20
flutter pub upgrade stale_charts

If the package is unmaintained and genuinely only needs stable DateFormat/NumberFormat APIs (most do), this is the one case where dependency_overrides is reasonable — and only to force intl to exactly the SDK pin, never past it:

dependency_overrides:
  intl: 0.20.2   # must match your SDK's pin exactly

Why dependency_overrides is usually the wrong fix

People reach for overrides first because it makes the error vanish. But overriding intl away from the SDK pin (e.g. forcing 0.19.0 on Flutter 3.32, or 0.20.x on Flutter 3.29) means flutter_localizations runs against locale data and APIs it was never built with. Mismatched intl overrides have produced real build failures reported on the Flutter issue tracker — errors that surface at compile or run time instead of at pub get, which is strictly worse. Rules of thumb:

  • Never override to a different minor version than the SDK pin.
  • Overriding to match the pin (Scenario 3) is fine — you're silencing a stale constraint, not changing what actually ships.
  • A patch-level bump (0.20.2 → 0.20.3) is low risk but still unsupported territory; prefer waiting for the caret-range pin to reach stable.
  • Delete the override once the offending package updates. Overrides in pubspec.yaml are invisible tech debt.

Will my DateFormat/NumberFormat code survive 0.19 → 0.20?

Almost certainly yes. intl 0.20 has no breaking DateFormat or NumberFormat API changes — the notable changes are a Dart ^3.3 requirement (any Flutter ≥3.19 satisfies it), CLDR data updates (v45/v46), typed symbol maps, and dropped http/web dependencies. Code like this compiles unchanged on both:

import 'package:intl/intl.dart';

String formatOrder(DateTime placedAt, double total, String locale) {
  final date = DateFormat.yMMMMd(locale).format(placedAt);
  final price = NumberFormat.currency(locale: locale, symbol: '€')
      .format(total);
  return '$date$price';
}

Two things can shift:

  1. Formatted output, not APIs. CLDR updates occasionally change separators, spacing (including non-breaking space characters), or currency symbols in specific locales. If you have golden tests or string-equality tests on formatted dates/numbers, re-record them after the upgrade rather than assuming a bug.
  2. Internals. If you poked at numberFormatSymbols dynamically, it's now typed as Map<String, NumberSymbols> — fix the types and move on.

Your ARB files need no changes at all: ICU message syntax, placeholders, and plurals are version-independent, so flutter gen-l10n output keeps working across the bump. That's also the argument for keeping translations in ARB rather than hardcoding formatted strings — the FlutterLocalisation ARB editor edits app_<locale>.arb files directly and validates ICU plural syntax (catching a missing few/many in Arabic, Polish, or Russian before your users do), so your translation layer stays stable no matter which intl version the SDK pins.

Quick reference

Symptom Fix
Your pubspec pins intl, SDK pin differs flutter pub add intl:any
Need intl 0.20.x on Flutter ≤3.29 flutter upgrade (pin moved in 3.32)
Transitive package wants older intl Upgrade the package; else override to the exact SDK pin
Fresh upgrade still failing flutter clean && flutter pub get; delete stale dependency_overrides

For a deeper tour of what intl itself gives you — formatting, plurals, Intl.message — see our Flutter intl package guide.

Stop fighting tooling, ship translations

Once pub get resolves again, the actual work is keeping dozens of ARB files consistent across locales. FlutterLocalisation gives you a web ARB editor with translation management and ICU plural validation across all your locales — with a free tier to start. Try FlutterLocalisation free and get your app_*.arb files out of raw JSON.