duckduckgo / duckduckgo/Android
[Bug] Got a StackOverflowError sometimes after delete a bookmark folder
Open
Nobody has claimed this yet.
bug
needs triage
- Dominant language
- Kotlin
- Stars
- 4.8k
- Forks
- 1.4k
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 170
Description
Describe the bug
Met with a StackOverflowError after deleted a bookmark folder.
FATAL EXCEPTION: DefaultDispatcher-worker-18
Process: com.duckduckgo.mobile.android.debug, PID: 6806
java.lang.StackOverflowError: stack size 1035KB
at java.lang.Object.hashCode(Object.java:122)
at java.util.WeakHashMap.hash(WeakHashMap.java:303)
at java.util.WeakHashMap.put(WeakHashMap.java:455)
at android.database.sqlite.SQLiteConnectionPool.finishAcquireConnectionLocked(SQLiteConnectionPool.java:1026)
at android.database.sqlite.SQLiteConnectionPool.tryAcquirePrimaryConnectionLocked(SQLiteConnectionPool.java:960)
at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:723)
at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:392)
at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:896)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:62)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1714)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1689)
at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.query(FrameworkSQLiteDatabase.kt:156)
at androidx.room.RoomDatabase.query(RoomDatabase.kt:484)
at androidx.room.util.DBUtil.query(DBUtil.kt:75)
at com.duckduckgo.savedsites.store.SavedSitesRelationsDao_Impl.countEntitiesInFolder(SavedSitesRelationsDao_Impl.kt:589)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.mapToBookmarkFolder(SavedSitesRepository.kt:597)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.folderContent(SavedSitesRepository.kt:201)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:181)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
...
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.traverseBranch(SavedSitesRepository.kt:185)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.getFolderBranch(SavedSitesRepository.kt:172)
at com.duckduckgo.savedsites.impl.RealSavedSitesRepository.deleteFolderBranch(SavedSitesRepository.kt:210)
at com.duckduckgo.savedsites.impl.bookmarks.BookmarksViewModel$delete$2.invokeSuspend(BookmarksViewModel.kt:328)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:811)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:715)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:702)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelled}@5d62044, Dispatchers.IO]
How to Reproduce
Do not know how to reproduce that precisely.
Expected behavior
Delete normally
Environment
- DDG App Version: 5.228.2
- Device: Pixel 8
- OS: Android 14
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in SavedSitesRepository.kt at getFolderBranch, deleteFolderBranch, traverseBranch, folderContent, and mapToBookmarkFolder, using the stack trace as the entry point. Inspect how folder relationships are traversed during deletion and look for the condition that allows traversal to continue recursively. Done means deleting a bookmark folder completes without StackOverflowError, with regression coverage for the affected traversal behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, kotlin, sqlite
- Domain
- database, mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 45/100