Skip to content

Auto upload: files are skipped forever after a folder is turned off and on, or after its settings are saved #17905

Description

@Blackclaws

⚠️ 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

A: turning a folder off and on

  1. Enable auto upload for a folder and let it upload some files.
  2. Delete some of those files on the server, or let some uploads fail.
  3. Turn auto upload off for the folder, then turn it on again, with "Also upload existing files" ticked.

B: saving folder settings

  1. Enable auto upload for a custom folder with "Also upload existing files" off.
  2. Add a file to the folder.
  3. Before the next scan runs, open the folder's settings and save them, without changing anything. Hiding or unhiding a folder has the same effect.

Expected behaviour

A: Files that are not on the server are uploaded again.
B: The new file is uploaded.

Actual behaviour

A: No file the folder had seen before is uploaded again, even if the server does not hold that file. Only deleting the folder entry and creating it again helps, and that is not possible for detected media folders such as the camera folder.
B: The file is never uploaded.

Cause (checked on master, 101ad50)

A. Turning a folder off calls FileUploadHelper.removeEntityFromUploadEntities (AutoUploadClickHandler.kt:70). That deletes the folder's upload entries but keeps its rows in the filesystem table, which stay marked as sent for upload. When the folder is turned on again, FileSystemRepository.insertOrReplace finds those rows unchanged and sent, finds no upload entry, and treats them as finished:

// FileSystemRepository.kt:253
val upload = getUpload(entity, syncedFolder, localPath, file) ?: return true

"Also upload existing files" has no effect, because shouldSkipFile only matters for files that have no row yet. FileSystemDao has no query to delete a folder's rows, so they are never cleared. The same rows also outlive a deleted folder.

B. AutoUploadDisplayItemFactory.updateAutoUploadFolderItem calls setEnabled(syncedFolder.isEnabled, clock.currentTime) on every save (line 125). createFromAutoUploadFolder also builds every list item with clock.currentTime as its enabled timestamp (line 149), and toggling visibility saves that item (AutoUploadClickHandler.kt:88-90). So any save moves enabledTimestampMs forward to now. With "Also upload existing files" off, shouldSkipFile then skips every file created before that moment that hadn't been scanned yet. For custom folders, BasicFileAttributes.creationTime() returns the last-modified time on Android, so files copied in with an old date are affected as well.

Minor: SyncedFolderEntity.enabledTimestampMs is declared as Int? and holds a millisecond timestamp, which overflows. Its only reader today (MediaFoldersDetectionWork) just checks for null.

These probably explain part of #15050, #15822 and #14385, and the "delete and recreate the folder" workaround mentioned in #15782 and #17801.

Android version

15

Device brand and model

Fairphone 4

Stock or custom OS?

Stock

Nextcloud android app version

35.0.2 (code analysis done on master, 101ad50)

Nextcloud server version

35.0.2

Using a reverse proxy?

Yes, Traefik

Android logs

No response

Server error logs

No response

Additional information

A fix is in Blackclaws/android, branch fix/auto-upload-stale-cache. The PR will follow.


Filed by Claude Code on behalf of @Blackclaws.

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions