Skip to content

Color.lerp asserts when mixing Display P3 and sRGB colors in ThemeData/ColorScheme #182777

Closed

Description

@spydon

Steps to reproduce

Use Color.from() with ColorSpace.displayP3 in a ColorScheme and render any widget that internally animates colors (e.g. TextField).

  MaterialApp(
    theme: ThemeData(
      colorScheme: ColorScheme.light(
        primary: const Color.from(
          alpha: 1,
          red: 0.0272,
          green: 0.2264,
          blue: 0.2928,
          colorSpace: ColorSpace.displayP3,
        ),
      ),
    ),
    home: const Scaffold(body: TextField()),
  )

Tap the TextField to trigger focus animation.

Expected results

Color.lerp should handle mixed color spaces gracefully, either by normalizing to a common space before interpolation or by documenting that ColorScheme/ThemeData only supports sRGB.

Actual results

The assertion fires because InputDecorator creates sRGB border colors internally and BorderSide.lerp calls Color.lerp with one sRGB and one Display P3 operand. The same issue affects AnimatedTheme (via ThemeData.lerp), TextStyleTween, ColorTween, and any other framework code that lerps theme-sourced colors against internally-created sRGB colors.

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown during paint():
'dart:ui/painting.dart': Failed assertion: line 428 pos 16: '<optimized out>': is not true.

Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=02_bug.yml

The relevant error-causing widget was:
  TextField TextField:file:///home/spydon/repos/h2-core/app/test/unit/display_p3_repro_test.dart:24:17

When the exception was thrown, this was the stack:
#2      Color.lerp (dart:ui/painting.dart:428:16)
#3      BorderSide.lerp (package:flutter/src/painting/borders.dart:271:22)
#4      UnderlineInputBorder.lerpFrom (package:flutter/src/material/input_border.dart:217:32)
#5      ShapeBorder.lerp (package:flutter/src/painting/borders.dart:516:36)
#6      _InputBorderTween.lerp (package:flutter/src/material/input_decorator.dart:110:45)
#7      Tween.transform (package:flutter/src/animation/tween.dart:369:12)
#8      Animatable.evaluate (package:flutter/src/animation/tween.dart:71:46)
#9      _InputBorderPainter.paint (package:flutter/src/material/input_decorator.dart:140:44)
#10     RenderCustomPaint._paintWithPainter (package:flutter/src/rendering/custom_paint.dart:593:13)
#11     RenderCustomPaint.paint (package:flutter/src/rendering/custom_paint.dart:646:7)
#12     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#13     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#14     _RenderDecoration.paint.doPaint (package:flutter/src/material/input_decorator.dart:1598:17)
#15     _RenderDecoration.paint (package:flutter/src/material/input_decorator.dart:1602:5)
#16     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#17     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#18     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#19     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#20     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#21     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#22     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#23     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#24     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#25     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#26     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#27     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#28     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#29     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#30     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#31     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#32     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#33     RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:3368:15)
#34     RenderCustomMultiChildLayoutBox.paint (package:flutter/src/rendering/custom_layout.dart:422:5)
#35     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#36     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#37     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#38     _RenderInkFeatures.paint (package:flutter/src/material/material.dart:634:11)
#39     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#40     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#41     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#42     RenderPhysicalModel.paint.<anonymous closure> (package:flutter/src/rendering/proxy_box.dart:2252:15)
#43     PaintingContext.pushClipRRect (package:flutter/src/rendering/object.dart:626:14)
#44     RenderPhysicalModel.paint (package:flutter/src/rendering/proxy_box.dart:2239:21)
#45     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#46     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#47     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#48     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#49     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:265:13)
#50     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:143:13)
#51     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:3429:7)
#52     PaintingContext._repaintCompositedChild (package:flutter/src/rendering/object.dart:180:11)
#53     PaintingContext.repaintCompositedChild (package:flutter/src/rendering/object.dart:125:5)
#54     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:1325:31)
#55     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:1335:15)
#56     AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:2137:31)
#57     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:495:5)
#58     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1430:15)
#59     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1345:9)
#60     AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:1960:9)
#63     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:74:41)
#64     AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1949:27)
#65     WidgetTester.pumpAndSettle.<anonymous closure> (package:flutter_test/src/widget_tester.dart:719:23)
<asynchronous suspension>
#66     TestAsyncUtils.guard.<anonymous closure> (package:flutter_test/src/test_async_utils.dart:130:27)
<asynchronous suspension>
#67     main.<anonymous closure> (file:///home/spydon/repos/h2-core/app/test/unit/display_p3_repro_test.dart:31:5)
<asynchronous suspension>
#68     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:192:15)
<asynchronous suspension>
#69     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1682:5)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from class _AssertionError, dart:async, and package:stack_trace)

The following RenderObject was being processed when the exception was fired: RenderCustomPaint#5c433:
  creator: CustomPaint ← _BorderContainer ← _Decorator ← InputDecorator ← AnimatedBuilder ← Listener ←
    RawGestureDetector ← TextSelectionGestureDetector ← Semantics ← AnimatedBuilder ← IgnorePointer ←
    TextFieldTapRegion ← ⋯
  parentData: offset=Offset(0.0, 0.0) (can use size)
  constraints: BoxConstraints(w=800.0, h=48.0)
  size: Size(800.0, 48.0)
  painter: null
  foregroundPainter: _InputBorderPainter#b661f
This RenderObject has no descendants.

Code sample

Code sample
import 'dart:ui' show ColorSpace;

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('Display P3 color in ColorScheme triggers Color.lerp assert', (
    tester,
  ) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          colorScheme: ColorScheme.light(
            primary: const Color.from(
              alpha: 1,
              red: 0.0272,
              green: 0.2264,
              blue: 0.2928,
              colorSpace: ColorSpace.displayP3,
            ),
          ),
        ),
        home: const Scaffold(
          body: TextField(),
        ),
      ),
    );

    // Trigger validation which causes AnimatedDefaultTextStyle to lerp
    await tester.tap(find.byType(TextField));
    await tester.pumpAndSettle();
  });
}

Screenshots or Video

No response

Logs

No response

Flutter Doctor output

Doctor output I tested both on main and stable with exactly the same results.

main:

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel main, 3.42.0-1.0.pre-222, on Ubuntu 24.04.4 LTS 6.8.0-100-generic, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Connected device (3 available)
[✓] Network resources

• No issues found!

stable:

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.41.1, on Ubuntu 24.04.4 LTS 6.8.0-100-generic, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Connected device (3 available)
[✓] Network resources

• No issues found!

Activity

  1. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    p: material_uimaterial_ui package in flutter/packages
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    team-designOwned by Design Languages team
    on Feb 25, 2026
  2. mbcorona commented on Feb 25, 2026

    @mbcorona
    Member

    Hi @spydon, thanks for the report and reproducible example! Labeling team-design to take a look at how ThemeData and InputDecorator handle mixed color spaces during lerping.

  3. added
    P2Important issues not at the top of the work list
    triaged-designTriaged by Design Languages team
    on Feb 25, 2026
  4. dkwingsmt commented on Feb 25, 2026

    @dkwingsmt
    Contributor

    Sounds like an oversight after adding support for color spaces. If Color.lerp throws for mixing color spaces then we should audit all uses of Color.lerp to eliminate similar errors.

  5. spydon commented on Feb 26, 2026

    @spydon
    ContributorAuthor

    Sounds like an oversight after adding support for color spaces. If Color.lerp throws for mixing color spaces then we should audit all uses of Color.lerp to eliminate similar errors.

    Can't we just add support for mixed color spaces in Color.lerp and it'll be automatically solved everywhere?

  6. spydon commented on Feb 26, 2026

    @spydon
    ContributorAuthor

    I'm thinking that we could just simply do this, what do you think?

  7. added a commit that references this issue on Mar 3, 2026
    8cd2df1
  8. added a commit that references this issue on Mar 10, 2026
    5090428
  9. github-actions commented on Mar 17, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  10. locked as resolved and limited conversation to collaborators on Mar 17, 2026
  11. added a commit that references this issue on Mar 26, 2026
    dee01bb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listframeworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: material_uimaterial_ui package in flutter/packagesteam-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions