Skip to content

High frequency crash - _TypeError at State.setState #138588

Closed

Description

@jacobsimionato

Copied from Google bug b/310712894:

An internal Google team is seeing as crash with over 5000 instances per day with this stack trace:

_TypeError
at State.setState (framework.dart:1223 )
at _AnimatedState._handleChange (transitions.dart:129 )
at _AnimatedState._handleChange (transitions.dart:128 )
at AnimationLocalListenersMixin.notifyListeners (listener_helpers.dart:161 )
at AnimationController._tick (animation_controller.dart:852 )
at AnimationController._tick (animation_controller.dart:841 )
at Ticker._tick (ticker.dart:249 )
at Ticker._tick (ticker.dart:243 )
at SchedulerBinding._invokeFrameCallback (binding.dart:1371 )
at SchedulerBinding.handleBeginFrame.<anonymous closure> (binding.dart:1218 )
at _LinkedHashMapMixin.forEach (compact_hash.dart:633 )
at SchedulerBinding.handleBeginFrame (binding.dart:1216 )
at SchedulerBinding._handleBeginFrame (binding.dart:1133 )
at SchedulerBinding._handleBeginFrame (binding.dart:1124 )
at _rootRunUnary (zone.dart:1415 )
at _rootRunUnary (zone.dart:1405 )
at _CustomZone.runUnary (zone.dart:1308 )
at _CustomZone.runUnaryGuarded (zone.dart:1217 )
at _invoke1 (hooks.dart:330 )
at PlatformDispatcher._beginFrame (platform_dispatcher.dart:350 )
at _beginFrame (hooks.dart:272 )
at _beginFrame (hooks.dart:270 )

We don't have a reproduction for this, but it's quite frequent, so I'm wondering if someone on the framework team could take a look in case it seems related to any recent changes.

This is occurring within a stack of completely Flutter framework code and the error message does not provide much context, so it's tricky to know where to start with reproducing this in the app. Any tips would be much appreciated here!

Activity

  1. HansMuller commented on Nov 17, 2023

    @HansMuller
    Contributor

    The code at the top of the stack hasn't changed in a year or more and unfortunately _TypeError doesn't reveal much. The line that's failing is:

    _element!.markNeedsBuild();

    Where _element is a StatefulElement.

  2. jonahwilliams commented on Nov 17, 2023

    @jonahwilliams
    Contributor

    TypeError would be because the element is null, I think the NPE is coerced to a TypeError. Potentially this is the element/context being used after the widget has been cleared, so something like a setState after an async call?

  3. jacobsimionato commented on Nov 17, 2023

    @jacobsimionato
    ContributorAuthor

    TypeError would be because the element is null, I think the NPE is coerced to a TypeError. Potentially this is the element/context being used after the widget has been cleared, so something like a setState after an async call?

    Oh that seems likely. Thank you for the help! It's difficult to try to guess where that is happening based on the trace - I'll ask the app team to think of recent changes to their code that could hold a reference to context over an async call.

  4. jacobsimionato commented on Nov 19, 2023

    @jacobsimionato
    ContributorAuthor

    From the app team on an internal bug:

    Regarding b/310712894#comment8: The setState after an async call would be the setState within the flutter animation code mentioned in the stack trace though, right? http://google3/third_party/dart/flutter/lib/src/widgets/transitions.dart;l=128;rcl=573307216

    That being said, if this isn't affecting any other clients, maybe we are doing something weird that causes the AnimationController to keep ticking for some reason even after its context has been disposed, triggering the unnecessary setState call in AnimationState. Even so, would it be appropriate to just guard the setState in transitions.dart with a mounted check? That would at least prevent the error there.

    Does it makes sense to guard this setState call? Or is that really just hiding a programming error that will likely have other consequences anyway.

    Seeing as it's quite difficult to find the root cause of this in application code (there are few recent animation changes in their codebase and no obvious bugs in them), I'm searching for other ways to make this tractable. Is there any way the framework could detect this issue sooner and/or use a more informative error message?

    I'll leave this without a priority tag so it can go through the proper triage process, but the internal bug is P1. I acknowledge it's still not clear if this issue is actionable for the Flutter team at all.

  5. goderbauer commented on Nov 22, 2023

    @goderbauer
    Member

    I would also conclude from the stack trace that _element is likely null when setState is called here:

    void _handleChange() {
    setState(() {
    // The listenable's state is our build state, and it changed already.
    });
    }

    What is puzzling: The _element is only nulled out when the StatefulElement is unmounted after State.dispose has been called, see:

    void _unmount(Element element) {
    assert(element._lifecycleState == _ElementLifecycle.inactive);
    assert(() {
    if (debugPrintGlobalKeyedWidgetLifecycle) {
    if (element.widget.key is GlobalKey) {
    debugPrint('Discarding $element from inactive elements list.');
    }
    }
    return true;
    }());
    element.visitChildren((Element child) {
    assert(child._parent == element);
    _unmount(child);
    });
    element.unmount();
    assert(element._lifecycleState == _ElementLifecycle.defunct);
    }

    In _AnimatedState.dispose we remove the _handleChange listener that is calling the problematic setState:

    void dispose() {
    widget.listenable.removeListener(_handleChange);
    super.dispose();
    }

    So, in theory, at the point in time where _element is null, the _handleChange shouldn't be registered anymore and it is a mystery to me right now why it would be called.

    Does it makes sense to guard this setState call? Or is that really just hiding a programming error that will likely have other consequences anyway.

    In theory (see above) it shouldn't be necessary to guard the setState, so, yeah, I am afraid that doing that is just hiding some other error somewhere...

    Is there any way the framework could detect this issue sooner and/or use a more informative error message?

    If we were able to repro this in a debug build, you'd likely get a better error message somewhere. In release builds a lot of the debug information is stripped out...

  6. goderbauer commented on Nov 28, 2023

    @goderbauer
    Member

    I think we need some more context where/when this crash is happening or a repo case to make progress.

  7. added
    will need additional triageThis issue or PR needs attention before being routed to secondary triage
    P2Important issues not at the top of the work list
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    and removed
    will need additional triageThis issue or PR needs attention before being routed to secondary triage
    on Nov 28, 2023
  8. 9 remaining items

  9. github-actions commented on Mar 1, 2024

    @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 1, 2024
  11. unlocked this conversation on Mar 5, 2024
  12. goderbauer commented on Mar 5, 2024

    @goderbauer
    Member

    Good news, somebody was able to reproduce this crash in #144087 (comment). Based on that, I was able to identify that the crash was caused by #136608. I am reverting that change in #144579.

  13. self-assigned this
    on Mar 5, 2024
  14. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Mar 5, 2024
  15. added
    r: fixedIssue is closed as already fixed in a newer version
    on Mar 6, 2024
  16. github-actions commented on Mar 20, 2024

    @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.

  17. locked as resolved and limited conversation to collaborators on Mar 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listc: crashStack traces logged to the consolecustomer: huggsy (g3)frameworkflutter/packages/flutter repository. See also f: labels.r: fixedIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions