Flutterレンダリングエラーを調べる

 ・ 7 min

photo by Karsten Winegeart on Unsplash

Flutterで作業していると、UI関連のエラーに最も多く遭遇すると思われますが、そのたびにコンソールに表示されるエラーが長くて複雑で、何をどう解決すればよいか分からない状況が多かったです。そこで今回、出力メッセージを一つずつ確認しながら、どのようにアプローチすればよいかまとめてみようと思います!

エラーメッセージ#

════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during performResize():
Vertical viewport was given unbounded height.
Viewports expand in the scrolling direction to fill their container. In this case, a vertical viewport was given an unlimited amount of vertical space in which to expand. This situation typically happens when a scrollable widget is nested inside another scrollable widget.
If this widget is always nested in a scrollable widget there is no need to use a viewport because there will always be enough vertical space for the children. In this case, consider using a Column or Wrap instead. Otherwise, consider using a CustomScrollView to concatenate arbitrary slivers into a single scrollable.
 
The relevant error-causing widget was:
    ListView ListView:file:///Users/ittae/development/ittae/lib/src/features/calendar/presentation/attendance_pages/widgets/attendance_result.dart:21:21
 
When the exception was thrown, this was the stack:
#0      debugCheckHasBoundedAxis.<anonymous closure> (package:flutter/src/rendering/debug.dart:337:13)
#1      debugCheckHasBoundedAxis (package:flutter/src/rendering/debug.dart:396:4)
#2      RenderViewport.computeDryLayout (package:flutter/src/rendering/viewport.dart:1384:12)
#3      RenderBox.performResize (package:flutter/src/rendering/box.dart:2668:12)
#4      RenderObject.layout (package:flutter/src/rendering/object.dart:2587:9)
#5      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#6      RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#7      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#8      RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#9      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#10     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#11     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#12     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#13     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#14     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#15     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#16     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#17     ChildLayoutHelper.layoutChild (package:flutter/src/rendering/layout_helper.dart:61:11)
#18     RenderFlex._computeSizes (package:flutter/src/rendering/flex.dart:985:73)
#19     RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:1051:32)
#20     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#21     RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:234:12)
#22     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#23     RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:234:12)
#24     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#25     MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:173:12)
#26     _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1092:7)
#27     MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:237:7)
#28     RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:404:14)
#29     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#30     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#31     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#32     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#33     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1448:11)
#34     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#35     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#36     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#37     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#38     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#39     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#40     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#41     ChildLayoutHelper.layoutChild (package:flutter/src/rendering/layout_helper.dart:61:11)
#42     RenderStack._computeSize (package:flutter/src/rendering/stack.dart:595:43)
#43     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:622:12)
#44     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#45     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#46     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#47     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#48     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#49     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#50     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#51     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#52     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#53     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#54     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#55     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#56     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3728:13)
#57     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#58     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#59     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#60     _RenderTheaterMixin.layoutChild (package:flutter/src/widgets/overlay.dart:1002:13)
#61     _RenderTheater.performLayout (package:flutter/src/widgets/overlay.dart:1311:9)
#62     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#63     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#64     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#65     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#66     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#67     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#68     RenderCustomPaint.performLayout (package:flutter/src/rendering/custom_paint.dart:569:11)
#69     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#70     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#71     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#72     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#73     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#74     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#75     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#76     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#77     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#78     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#79     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#80     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#81     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#82     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#83     RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#84     RenderView.performLayout (package:flutter/src/rendering/view.dart:281:14)
#85     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2446:7)
#87     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1065:15)
#88     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:602:23)
#89     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:1164:13)
#90     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:468:5)
#91     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1397:15)
#92     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1318:9)
#93     SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:1040:9)
#94     PlatformDispatcher.scheduleWarmUpFrame.<anonymous closure> (dart:ui/platform_dispatcher.dart:837:16)
#98     _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
(elided 3 frames from class _Timer and dart:async-patch)
 
The following RenderObject was being processed when the exception was fired: RenderViewport#d5613 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
    needs compositing
    parentData: <none> (can use size)
    constraints: BoxConstraints(0.0<=w<=398.0, 0.0<=h<=Infinity)
    size: MISSING
    axisDirection: down
    crossAxisDirection: right
    offset: ScrollPositionWithSingleContext#b7b6f(offset: 0.0, range: null..null, viewport: null, ScrollableState, AlwaysScrollableScrollPhysics -> BouncingScrollPhysics -> RangeMaintainingScrollPhysics, IdleScrollActivity#4402f, ScrollDirection.idle)
    anchor: 0.0
    center child: RenderSliverPadding#bbdeb NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
        parentData: paintOffset=Offset(0.0, 0.0)
        constraints: MISSING
        geometry: null
        padding: EdgeInsets.zero
        textDirection: ltr
        child: RenderSliverList#ccfb1 NEEDS-LAYOUT NEEDS-PAINT
            parentData: paintOffset=Offset(0.0, 0.0)
            constraints: MISSING
            geometry: null
            no children current live
RenderObject: RenderViewport#d5613 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
    needs compositing
    parentData: <none> (can use size)
    constraints: BoxConstraints(0.0<=w<=398.0, 0.0<=h<=Infinity)
    size: MISSING
    axisDirection: down
    crossAxisDirection: right
    offset: ScrollPositionWithSingleContext#b7b6f(offset: 0.0, range: null..null, viewport: null, ScrollableState, AlwaysScrollableScrollPhysics -> BouncingScrollPhysics -> RangeMaintainingScrollPhysics, IdleScrollActivity#4402f, ScrollDirection.idle)
    anchor: 0.0
    center child: RenderSliverPadding#bbdeb NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
        parentData: paintOffset=Offset(0.0, 0.0)
        constraints: MISSING
        geometry: null
        padding: EdgeInsets.zero
        textDirection: ltr
        child: RenderSliverList#ccfb1 NEEDS-LAYOUT NEEDS-PAINT
            parentData: paintOffset=Offset(0.0, 0.0)
            constraints: MISSING
            geometry: null
            no children current live
════════════════════════════════════════════════════════════════════════════════
 
════════ Exception caught by rendering library ═════════════════════════════════
RenderBox was not laid out: RenderViewport#d5613 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 2164 pos 12: 'hasSize'
The relevant error-causing widget was:
    ListView ListView:file:///Users/ittae/development/ittae/lib/src/features/calendar/presentation/attendance_pages/widgets/attendance_result.dart:21:21
════════════════════════════════════════════════════════════════════════════════
 
この後ろに数個から数十個続くRenderBox was not laid outエラーは省略します!

エラーメッセージの核心を把握する#

エラーメッセージのすべての内容を確認するのも良いですが、実際に開発した部分よりもフレームワークやSDKで処理される箇所で出力されるメッセージであることがほとんどです。そのため一つずつ確認しても、フレームワークのソースコードを把握していないと素早く役に立ちませんでした。

エラーの原因を簡単に把握する方法として、ログを解釈するのが役立ちます。長いエラーログの中で主に最初のエラーメッセージ発生したウィジェットの部分が最も重要です。Flutterの長いログは通常、複数段階のレンダリング過程を経て問題が発生した結果であり、最初に出たエラーが核心的なエラーである可能性が高いです。

全体の出力に集中するよりも、いくつかの重要なキーワードを探す必要があります。Flutterでエラーが出る主な理由として、あるウィジェットを追加・変更した際のレイアウト関連の問題である確率が高いです。

エラーの種類を調べる#

開発環境のデバッグコンソールを見ると、赤いものと青い文字のものがありますが、明らかに赤い部分を詳しく見る必要がありそうです。赤いメッセージの前後の説明も一緒に読むと、問題解決にさらに役立ちます。通常、出力が長いので全体的に目に入りにくいですが、最初のエラーメッセージを時間をかけて確認するのが、問題を素早く解決できる方法です。

このエラーメッセージはListViewを使っていた時に出たものです。ListViewは通常の状況ではうまく動きますが、ListViewをColumnの子として追加し、サイズを指定していなかったため、高さが無限大の状況となりエラーが発生したのでした。

image

解決方法#

Columnの子にあるListViewをExpandedで囲む

Expanded(
  child: ListView(
    children: [...],
  ),
)

ContainerやSizedBoxウィジェットで高さを指定する

SizedBox(
  height: 300.0, // 任意の高さ
  child: ListView(
    children: [...],
  ),
)

ListViewにshrinkWrap: trueを追加する

ListView(
  shrinkWrap: true,
  children: [...],
)

まとめ

  • 最上部の最初のエラーメッセージに集中して確認する - ほとんどの解決策は最初のエラーに基づいて見つけられる
  • エラーメッセージからウィジェットと行番号を追跡して、どこで問題が発生したか正確に把握する
  • Flutter公式ドキュメントStack Overflowを活用して類似のエラーの解決策を探す

Here and now...breathe and relax...in battle and in life.

— Dan Millman


他の投稿
VS Codeでおすすめの拡張機能 커버 이미지
 ・ 2 min

VS Codeでおすすめの拡張機能

FlutterでFeature-Firstアーキテクチャの実例紹介 커버 이미지
 ・ 8 min

FlutterでFeature-Firstアーキテクチャの実例紹介

ダウンロードしたFlutterプロジェクトが実行できない時の解決方法 커버 이미지
 ・ 1 min

ダウンロードしたFlutterプロジェクトが実行できない時の解決方法