nextcloud / nextcloud/android

Local folder picker crashes the app: UncheckedIOException from Files.list() escapes the IOException catch in FileHelper.listDirectoryEntries

Offen Anfängerfreundlich
#17,533 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
0. Needs triage
Vorherrschende Sprache
Kotlin
Sterne
5.6k
Forks
2k
Ø Merge
2 T. 18 Std.
Gemergte PRs (30 T.)
92

Beschreibung

### ⚠️ Before posting ⚠️

- [x] This is a **bug**, not a question or an enhancement.
- [x] I've [searched for similar issues](https://github.com/nextcloud/android/issues) and didn't find a duplicate.
- [x] I've written a clear and descriptive title for this issue, not just "Bug" or "Crash".
- [x] I agree to follow Nextcloud's [Code of Conduct](https://nextcloud.com/contribute/code-of-conduct/).

### Steps to reproduce

1. Settings → Auto upload → ⋮ → "Set custom folder".
2. 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).
3. 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`:

```kotlin
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
```java
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`

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Start in FileHelper.kt at listDirectoryEntries and inspect how Files.list() reports failures during terminal iteration; then check LocalFileListAdapter.kt at loadRemainingEntries() for the background-task boundary. Confirm that directory-read failures no longer terminate the app, that the picker retains the readable entries or shows an empty list, and whether the fix needs backporting to the 34.1.1 line.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
kotlin
Bereich
mobile
Issue-Typ
Bug
Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Aktivitätsstatus
Aktiv
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
84/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.