Skip to content

Thumbnails duplications, missing thumbnails and files failing to download #17918

Open

Description

@funmaker

⚠️ Before posting ⚠️

  • This is a bug, not a question or an enhancement.
  • I've searched for similar issues and didn't find a duplicate.
  • I've written a clear and descriptive title for this issue, not just "Bug" or "Crash".
  • I agree to follow Nextcloud's Code of Conduct.

Steps to reproduce

  1. Open Discord
  2. Click share file
  3. In share popup choose Nextcloud
  4. Navigate to folder full of images

Expected behaviour

  1. All thumbnails load(preferably from cache)
  2. Same files do not appear more than once
  3. Files can be shared

Actual behaviour

  1. Some thumbnails never work
  2. Some files appear twice
  3. Some files fail to sync/share

Android version

16

Device brand and model

Samsung Galaxy S10+

Stock or custom OS?

Custom (explain in "additional information")

Nextcloud android app version

35.0.2

Nextcloud server version

26

Using a reverse proxy?

Yes

Android logs

No response

Server error logs

Additional information

My OS is lineage OS. There is no file at storage/emulated/0/data/nextcloud.log.

I had these 3 issues for a while. I suspect that they are at least partially because of me using adb to just pull and push all the files when changing phone, but some of these issues like broken thumbnails were older than that. I tasked Deepseek with debugging these issues and it found couple of problems with both with the state of files on my phone and code itself. In particular, it seems there is a race condition that causes duplications in file database and wrong thumbnail size reporting which breaks thumbnails for files smaller than the thumbnail. I am not going to pretend to be experienced in Java nor your codebase, but I've pushed commit that fixes code issues to my fork. It's fairly short so you might find it useful, but take it with grain of salt(claude had some concerns on the quality of this fix). funmaker@c8c7f75

Here is a more in detail description from Deepseek agent:

Investigated all three against the live device, server, app database, and source.
Root causes
1. Duplicate files in /xD/reaction/
The file database itself contained duplicate rows, not the server. For example:
_id 1800  /xD/reaction/001.jpg  remote_id 00427388...
_id 2086  /xD/reaction/001.jpg  remote_id 00427388...
There were 354 duplicate-path groups (580 rows for 292 files in /xD/reaction/).
I reproduced the creation mechanism: forcing two concurrent queryChildDocuments() calls on the same stale folder started two RefreshFolderOperations at once. Both took a database snapshot before either saved, both saw the file as “new”, and both inserted it. FileDataStorageManager.saveFolder() does a check-then-insert without serialization, so it is a race.
2. Broken/missing thumbnails
Two bugs:
- DocumentsStorageProvider.openDocumentThumbnail() returned a generated PNG thumbnail but told the caller its length was file.fileLength — the original file size. Small images often have thumbnails larger than the original, so the thumbnail was truncated and failed to decode. Example: /xD/reaction/001.jpg is 13,645 bytes, but its generated thumbnail file was 60,533 bytes; only 13,645 bytes were exposed.
- DiskLruImageCacheFileProvider.getParcelFileDescriptorForOCFile() called Files.createFile() and only wrote the bitmap inside the same try. If the cache file already existed, createFile() threw and the write was skipped, leaving stale/old thumbnail data forever. Cache files were also keyed only by base filename, so equal filenames in different folders collided.
- Additionally ThumbnailsCacheManager.containsBitmap() dereferenced the disk cache before its async initialization finished, and addBitmapToCache() silently dropped images during startup, so first thumbnails were not cached.
3. /xD/reaction/111665930_..._n.png cannot be opened/shared
This was a device MediaProvider ownership problem, not a Nextcloud logic bug.
The file was registered in MediaProvider’s external.db as:
owner_package_name = com.android.shell
while the app is com.nextcloud.client. The app therefore got EACCES when opening/replacing it. 352 of 593 files under the Nextcloud media directory had the same wrong owner. Because the DB row had an empty etag, DocumentOpener also tried to re-download it; the HTTP download succeeded, but Files.move(..., REPLACE_EXISTING) then failed with EACCES, and opening the existing local file failed too.
Changes made
Source changes in the working tree:
- DocumentLister.kt
- Deduplicates listed/search results by remoteId / decrypted path.
- Coalesces concurrent folder reload jobs per document so repeated queryChildDocuments() calls do not start parallel refreshes.
- FileDataStorageManager.java
- Serializes saveFolder() through a process-wide lock, eliminating the check-then-insert race that created duplicate rows.
- DocumentsStorageProvider.kt
- Returns the actual thumbnail file size via descriptor.statSize instead of the original document size.
- DiskLruImageCacheFileProvider.java
- Always overwrites the generated thumbnail, uses a unique thumbnail filename (remoteId), and reports the real file.
- ThumbnailsCacheManager.java
- containsBitmap() now waits for disk-cache initialization and is null-safe.
- addBitmapToCache() waits for initialization instead of silently dropping thumbnails.
Device fixes applied
- Removed 354 duplicate filelist rows and reparented any affected children. Verified PRAGMA integrity_check = ok; /xD/reaction/ now returns 292 rows, no duplicates.
- Backup left at /data/local/tmp/filelist-before-dedupe.db.
- Repaired MediaProvider ownership for all 593 Nextcloud media files (com.android.shell / old ownership → com.nextcloud.client), preserving the files_update trigger and restarting MediaProvider.
- Deleted and re-downloaded the originally failing 111665930_..._n.png.
Verified content read now succeeds for:
- /xD/reaction/001.jpg — 13,645 bytes
- /xD/reaction/111665930_316871886117476_1713782649053830776_n.png — 92,032 bytes
- /xD/reaction/1708011767812109.jpg — 39,491 bytes
Status / caveat
The device-side duplicate cleanup and MediaProvider repair take effect immediately. The source fixes for duplicate prevention and thumbnails require rebuilding/reinstalling the APK; this environment has no Android SDK/AGP cache, so I could not compile or install the patched build here. The changes are uncommitted for human review as required by the project’s AI contribution policy.
Build · DeepSeek V4.1 Flash · 37m 33s · 47.8 tok/s

After these devices fixes and rebuilding the app for my device all the issues were resolved.

Activity

  1. daniele-verducci commented on Nov 13, 2026

    @daniele-verducci
    Contributor

    Hey @funmaker ,
    thanks for reporting!
    We may be lucky here: a problem causing duplicates for files in database was fixed here: #17941
    This will be released in 35.1.0, but you can already try it in latest RC: https://github.com/nextcloud/android/tree/rc-35.1.0-02
    Can I ask you to try and report if this fixes it? If it does, feel free to close the issue.

    Thank you!

  2. funmaker commented on Nov 14, 2026

    @funmaker
    Author

    Hi @daniele-verducci

    The issue that causes duplication I can't reproduce myself, it seems to come from some race condition but based on Deepseek's analysis this version should prevent new rows like that from being created. But there seems to be no code in share menu to actually deduplicate rows that were made before the update, DocumentsProvider still shows duplicate files. The in app does use distinctBy { it.fileName } which hides the duplicates. Maybe some startup/update cleanup routine that will remove them instead of hiding? Unless there is something like that and I missed it.

    The other issues do remain. Thumbnails that are larger than the file itself are still broken in share menu. And if two files in different locations share same name, both will use same one thumbnail in share menu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions