⚠️ Before posting ⚠️
Steps to reproduce
- Settings → Auto upload → ⋮ → "Set custom folder".
- In the local folder picker, browse into a large directory under
/storage/emulated/0/Android/media/… (in my case com.whatsapp/WhatsApp/Media/WhatsApp Images, ~11 600 files, and its Sent subdirectory).
- Keep the device busy at the same time (several auto-upload rules were uploading in the background here).
The directory read fails part-way through iteration with Software caused connection abort from the emulated-storage layer. That failure is intermittent and I cannot trigger it on demand — but when it happens, the app dies instead of showing an empty/partial list.
Expected behaviour
A failed directory read is logged and the picker shows what it could read (the catch in FileHelper.listDirectoryEntries is clearly written with exactly that intent).
Actual behaviour
The whole app is killed. The exception escapes the background executor task, so there is no chance to recover.
The catch cannot fire, and this is visible in the source rather than inferred:
FileHelper.listDirectoryEntries (34.1.1) uses Files.list(...), whose lazy stream reports directory-read failures from the terminal operation as java.io.UncheckedIOException — a RuntimeException, not an IOException:
return try {
Files.list(directory.toPath())
.map { it.toFile() }
…
.collect(Collectors.toList())
} catch (e: IOException) { // never reached for UncheckedIOException
Log_OC.d(TAG, "listDirectoryEntries: $e")
emptyList()
}
LocalFileListAdapter.loadRemainingEntries() calls it on a pool thread with no guard, so the UncheckedIOException terminates the thread and takes the process with it.
Two small notes that may save reviewer time:
- Adding
catch (e: UncheckedIOException) (or catching its cause) next to the existing IOException branch restores the intended behaviour.
FileHelper on master has since been rewritten to forEachDirectoryPage using Files.newDirectoryStream with catch (IOException) + catch (DirectoryIteratorException), which does cover the iteration failure. So master may already be fine and this report is mainly about the released 34.1.1 line — worth confirming whether a backport is wanted.
Android version
17
Device brand and model
Samsung SM-F976B (Galaxy Z Fold8), stock
Stock or custom OS?
Stock
Nextcloud android app version
34.1.1 (340010190, gplay)
Nextcloud server version
31.0.14
Using a reverse proxy?
Yes
Android logs
Cause of error
Exception in thread "pool-27-thread-1" java.io.UncheckedIOException: java.nio.file.FileSystemException: /storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/WhatsApp Images/Sent: Software caused connection abort
at java.nio.file.Files$2.hasNext(Files.java:3729)
at java.util.Spliterators$IteratorSpliterator.tryAdvance(Spliterators.java:1949)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:156)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:592)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:578)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:564)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:267)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:748)
at com.nextcloud.utils.FileHelper.listDirectoryEntries(FileHelper.kt:31)
at com.owncloud.android.ui.adapter.LocalFileListAdapter.loadRemainingEntries(LocalFileListAdapter.java:434)
at com.owncloud.android.ui.adapter.LocalFileListAdapter.lambda$swapDirectory$2(LocalFileListAdapter.java:405)
at com.owncloud.android.ui.adapter.LocalFileListAdapter.$r8$lambda$EFQ1jO9hT3yhM5CFqUk4qO5Vyvg(LocalFileListAdapter.java:0)
at com.owncloud.android.ui.adapter.LocalFileListAdapter$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1100)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:1572)
Caused by: java.nio.file.FileSystemException: /storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/WhatsApp Images/Sent: Software caused connection abort
at sun.nio.fs.UnixDirectoryStream$UnixDirectoryIterator.readNextEntry(UnixDirectoryStream.java:180)
at sun.nio.fs.UnixDirectoryStream$UnixDirectoryIterator.hasNext(UnixDirectoryStream.java:210)
at java.nio.file.Files$2.hasNext(Files.java:3727)
…
App information
- ID:
com.nextcloud.client
- Version:
340010190
- Build flavor:
gplay
Device information
- Brand:
samsung
- Device:
q8q
- Model:
SM-F976B
- Id:
CP2A.260605.016
- Product:
q8qxeea
Firmware
- SDK:
37
- Release:
17
- Incremental:
F976BXXS2AZH7
Steps to reproduce
/storage/emulated/0/Android/media/…(in my casecom.whatsapp/WhatsApp/Media/WhatsApp Images, ~11 600 files, and itsSentsubdirectory).The directory read fails part-way through iteration with
Software caused connection abortfrom the emulated-storage layer. That failure is intermittent and I cannot trigger it on demand — but when it happens, the app dies instead of showing an empty/partial list.Expected behaviour
A failed directory read is logged and the picker shows what it could read (the
catchinFileHelper.listDirectoryEntriesis clearly written with exactly that intent).Actual behaviour
The whole app is killed. The exception escapes the background executor task, so there is no chance to recover.
The
catchcannot fire, and this is visible in the source rather than inferred:FileHelper.listDirectoryEntries(34.1.1) usesFiles.list(...), whose lazy stream reports directory-read failures from the terminal operation asjava.io.UncheckedIOException— aRuntimeException, not anIOException:LocalFileListAdapter.loadRemainingEntries()calls it on a pool thread with no guard, so theUncheckedIOExceptionterminates the thread and takes the process with it.Two small notes that may save reviewer time:
catch (e: UncheckedIOException)(or catching itscause) next to the existingIOExceptionbranch restores the intended behaviour.FileHelperon master has since been rewritten toforEachDirectoryPageusingFiles.newDirectoryStreamwithcatch (IOException)+catch (DirectoryIteratorException), which does cover the iteration failure. So master may already be fine and this report is mainly about the released 34.1.1 line — worth confirming whether a backport is wanted.Android version
17
Device brand and model
Samsung SM-F976B (Galaxy Z Fold8), stock
Stock or custom OS?
Stock
Nextcloud android app version
34.1.1 (340010190, gplay)
Nextcloud server version
31.0.14
Using a reverse proxy?
Yes
Android logs
Cause of error
App information
com.nextcloud.client340010190gplayDevice information
samsungq8qSM-F976BCP2A.260605.016q8qxeeaFirmware
3717F976BXXS2AZH7