Skip to content

Bug: OutOfMemoryError in Polycentric getSystemState / CRDT deserialization when liking a video #3335

@Marshall-Wagner

Description

@Marshall-Wagner

Reproduction steps

No single deterministic step — it crashes intermittently during normal use once the
Polycentric identity has grown large:

  1. Use a Polycentric identity that has a lot of accumulated activity over time.
  2. Browse and load videos normally (e.g. open videos from a playlist / subscriptions).
    No specific button press is required.
  3. The app OOM-crashes — sometimes on a background okhttp network thread with no
    interaction (stack 2), and sometimes via the like/dislike pill's opinion() path
    (stack 1).

Common factor: the heap reaches its ~768 MB limit while Polycentric's full SystemState
is being deserialized (getSystemState → StorageTypeCRDTSetItem.fromProto).

Actual result

Actual result: the app crashes to Grayjay's in-app "App Error" screen with a
java.lang.OutOfMemoryError (heap already at its ~768 MB growth limit). Screenshot below;
full text stacks are in the logs section.

Image Image

Expected result

Loading a video, reading/displaying its existing rating state, and
liking/rating should all work without crashing, no matter how large the Polycentric
identity has grown. Polycentric's SystemState handling should not load the entire dataset
into memory in a way that can exhaust the heap. If the stored state is too large to load
safely, the app should degrade gracefully (e.g. fall back to the existing v208 "disable
Polycentric on problems" path) instead of hard-crashing the whole app.

Grayjay Version

381

What plugins are you seeing the problem on?

YouTube

Plugin Version

340 (for YouTube)

Which android version are you using?

Android 14 (SDK 34)

Which device are you using?

ASUS ROG Phone 6 (ASUS_AI2201)

Which operating system are you using?

ASUS ZenUI, Android 14 (China/CN ROM build CN_34.0210.0210.276)

When do you experience the issue?

  • While logged in
  • While logged out
  • N/A

Are you using a VPN?

No

References

References:

Relevant log output

Stack 1: background okhttp network thread (no interaction; heap already exhausted):

java.lang.OutOfMemoryError: Failed to allocate a 32 byte allocation with 4375088 free bytes and 4272KB until OOM, target footprint 805306368, growth limit 805306368; giving up on allocation because <1% of heap free after GC.
	at java.util.ArrayList.iterator(ArrayList.java:954)
	at okhttp3.internal.concurrent.TaskRunner.awaitTaskToRun(TaskRunner.kt:186)
	at okhttp3.internal.concurrent.TaskRunner$runnable$1.run(TaskRunner.kt:71)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
	at java.lang.Thread.run(Thread.java:1012)

Stack 2: Polycentric SystemState deserialization via like/dislike pill:

Version information (version_name = 381, version_code = 381, flavor = stable, build_type = release)
Device information (brand= asus, manufacturer = asus, device = ASUS_AI2201, version-sdk = 34, version-os = )

(e, ExceptionActivity, 2026-06-04 08:55:51): Uncaught exception ("Unknown Context"): Failed to allocate a 32 byte allocation with 603872 free bytes and 589KB until OOM, target footprint 805306368, growth limit 805306368; giving up on allocation because <1% of heap free after GC.

java.lang.OutOfMemoryError: Failed to allocate a 32 byte allocation with 603872 free bytes and 589KB until OOM, target footprint 805306368, growth limit 805306368; giving up on allocation because <1% of heap free after GC.
	at com.futo.polycentric.core.StorageTypeCRDTSetItem$Companion.fromProto(Models.kt:659)
	at com.futo.polycentric.core.StorageTypeSystemState$Companion.fromProto(Models.kt:768)
	at com.futo.polycentric.core.SqlLiteStore.getSystemState(SqlLiteStore.kt:22)
	at com.futo.polycentric.core.ProcessHandle.ingest(ProcessHandle.kt:230)
	at com.futo.polycentric.core.ProcessHandle.publish(ProcessHandle.kt:223)
	at com.futo.polycentric.core.ProcessHandle.opinion(ProcessHandle.kt:30)
	at com.futo.platformplayer.fragment.mainactivity.main.VideoDetailView$setVideoDetails$5$1.invokeSuspend$lambda$0(VideoDetailView.kt:1761)
	at com.futo.platformplayer.fragment.mainactivity.main.VideoDetailView$setVideoDetails$5$1.$r8$lambda$JT2GdukYIXFTkA76mepEuOecyGc(Unknown Source:0)
	at com.futo.platformplayer.fragment.mainactivity.main.VideoDetailView$setVideoDetails$5$1$$ExternalSyntheticLambda0.invoke(D8$$SyntheticClass:0)
	at com.futo.platformplayer.constructs.Event1.emit(Event.kt:99)
	at com.futo.platformplayer.views.pills.PillRatingLikesDislikes.like(PillRatingLikesDislikes.kt:148)
	at com.futo.platformplayer.views.pills.PillRatingLikesDislikes._init_$lambda$0$0(PillRatingLikesDislikes.kt:57)
	at com.futo.platformplayer.views.pills.PillRatingLikesDislikes.$r8$lambda$v50kJFCP5LM2zjr4LCU-o0F8MZA(Unknown Source:0)
	at com.futo.platformplayer.views.pills.PillRatingLikesDislikes$$ExternalSyntheticLambda0.invoke(D8$$SyntheticClass:0)
	at com.futo.platformplayer.states.StatePolycentric.requireLogin(StatePolycentric.kt:238)
	at com.futo.platformplayer.views.pills.PillRatingLikesDislikes._init_$lambda$0(PillRatingLikesDislikes.kt:57)
	at com.futo.platformplayer.views.pills.PillRatingLikesDislikes.$r8$lambda$iNcfvH95pjrzX8uMcuTrsGrRGvQ(Unknown Source:0)
	at com.futo.platformplayer.views.pills.PillRatingLikesDislikes$$ExternalSyntheticLambda1.onClick(D8$$SyntheticClass:0)
	at android.view.View.performClick(View.java:7680)
	at android.view.View.performClickInternal(View.java:7657)
	at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
	at android.view.View$PerformClick.run(View.java:30196)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:245)
	at android.os.Looper.loop(Looper.java:364)
	at android.app.ActivityThread.main(ActivityThread.java:8439)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:977)

Stack 3: UI layout/measure pass (heap already exhausted):

Version information (version_name = 381, version_code = 381, flavor = stable, build_type = release)
Device information (brand= asus, manufacturer = asus, device = ASUS_AI2201, version-sdk = 34, version-os = )

(e, ExceptionActivity, 2026-06-05 08:54:41): Uncaught exception ("Unknown Context"): Failed to allocate a 160 byte allocation with 355256 free bytes and 346KB until OOM, target footprint 805306368, growth limit 805306368; giving up on allocation because <1% of heap free after GC.

java.lang.OutOfMemoryError: Failed to allocate a 160 byte allocation with 355256 free bytes and 346KB until OOM, target footprint 805306368, growth limit 805306368; giving up on allocation because <1% of heap free after GC.
	at androidx.constraintlayout.motion.widget.MotionConstrainedPoint.<init>(MotionConstrainedPoint.java:50)
	at androidx.constraintlayout.motion.widget.MotionController.<init>(MotionController.java:96)
	at androidx.constraintlayout.motion.widget.MotionLayout$Model.build(MotionLayout.java:2919)
	at androidx.constraintlayout.motion.widget.MotionLayout.setupMotionViews(MotionLayout.java:1805)
	at androidx.constraintlayout.motion.widget.MotionLayout.access$1400(MotionLayout.java:1030)
	at androidx.constraintlayout.motion.widget.MotionLayout$Model.reEvaluateState(MotionLayout.java:2825)
	at androidx.constraintlayout.motion.widget.MotionLayout.onMeasure(MotionLayout.java:3052)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608)
	at android.widget.LinearLayout.measureVertical(LinearLayout.java:878)
	at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608)
	at android.widget.LinearLayout.measureVertical(LinearLayout.java:878)
	at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at com.android.internal.policy.DecorView.onMeasure(DecorView.java:774)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:4373)
	at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2870)
	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3203)
	at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2566)
	at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9569)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1425)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1434)
	at android.view.Choreographer.doCallbacks(Choreographer.java:1037)
	at android.view.Choreographer.doFrame(Choreographer.java:965)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1408)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:245)
	at android.os.Looper.loop(Looper.java:364)
	at android.app.ActivityThread.main(ActivityThread.java:8439)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:977)

Crash 4:

Version information (version_name = 381, version_code = 381, flavor = stable, build_type = release)
Device information (brand= asus, manufacturer = asus, device = ASUS_AI2201, version-sdk = 34, version-os = )

(e, ExceptionActivity, 2026-06-05 00:36:07): Uncaught exception ("Unknown Context"): Failed to allocate a 160 byte allocation with 355256 free bytes and 346KB until OOM, target footprint 805306368, growth limit 805306368; giving up on allocation because <1% of heap free after GC.

java.lang.OutOfMemoryError: Failed to allocate a 160 byte allocation with 355256 free bytes and 346KB until OOM, target footprint 805306368, growth limit 805306368; giving up on allocation because <1% of heap free after GC.
	at androidx.constraintlayout.motion.widget.MotionConstrainedPoint.<init>(MotionConstrainedPoint.java:50)
	at androidx.constraintlayout.motion.widget.MotionController.<init>(MotionController.java:96)
	at androidx.constraintlayout.motion.widget.MotionLayout$Model.build(MotionLayout.java:2919)
	at androidx.constraintlayout.motion.widget.MotionLayout.setupMotionViews(MotionLayout.java:1805)
	at androidx.constraintlayout.motion.widget.MotionLayout.access$1400(MotionLayout.java:1030)
	at androidx.constraintlayout.motion.widget.MotionLayout$Model.reEvaluateState(MotionLayout.java:2825)
	at androidx.constraintlayout.motion.widget.MotionLayout.onMeasure(MotionLayout.java:3052)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608)
	at android.widget.LinearLayout.measureVertical(LinearLayout.java:878)
	at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608)
	at android.widget.LinearLayout.measureVertical(LinearLayout.java:878)
	at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7041)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at com.android.internal.policy.DecorView.onMeasure(DecorView.java:774)
	at android.view.View.measure(View.java:27162)
	at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:4373)
	at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2870)
	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3203)
	at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2566)
	at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9569)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1425)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1434)
	at android.view.Choreographer.doCallbacks(Choreographer.java:1037)
	at android.view.Choreographer.doFrame(Choreographer.java:965)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1408)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:245)
	at android.os.Looper.loop(Looper.java:364)
	at android.app.ActivityThread.main(ActivityThread.java:8439)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:977)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions