Skip to content

Text app does not detect changed files on external ressources #9236

Description

@hede5562

Describe the bug
Nextcloud text does not detect changes to files in the filesystem. Overwrites changed files with stale content.

To Reproduce
Steps to reproduce the behavior:

  1. Add an external to nextcloud
  2. create file test.md on the external storage
  3. open test.md in nextcloud
  4. add text "nexlcoudcontent" to the file via nextcloud text
  5. open test.md outside of nextcloud, where the external(!) storage is primarily used
  6. change text to "externalcontent" in the file via some external resource
  7. open test.md in nextcloud
  8. content of the file is still "nextcloudcontent"
  9. change content to "stillnextcloudcontent"
  10. safe the file in nextcloud
  11. there is NO conflict, the real filesystem content is ignored and overwritten

Even the following is possible:

  1. Add an external to nextcloud
  2. create file test.md on the external storage
  3. open test.md in nextcloud
  4. add text "nexlcoudcontent" to the file via nextcloud text
  5. open test.md outside of nextcloud, where the external(!) storage is primarily used
  6. change text to "externalcontent" in the file via some external resource
  7. open test.md in nextcloud
  8. content of the file is still "nextcloudcontent"
  9. rename the file to test.txt within nextcloud
  10. open test.txt in nextcloud
  11. content of the file is "externalcontent" now
  12. rename the file back to test.md
  13. open test.md in nextcloud
  14. content of the file changes back to "nextcloudcontent"

even running "occ files:scan" in between does not make any difference. Even if "occ files:scan" does detect the changed file, the integrated nextcloud text editor still uses its outdated cache.

Expected behavior
Nextcloud should always(!) check if the file on the filesystem has changed and should deny to use other sources if the file has changed
At least it should use a timestamp within its non-filesystem-cache for cached files and should compare these when writing: if the timestamp in the non-filesystem-cache and the timestamp of the file in the filesystem are different, then obviously some external change was made to the file; in this nextcloud should deny overwriting the file and instead show a conflict warning!

Silently overwriting changed files on external(!) storage is fatal!

This already worked in the past. I'm using this for some time and in the past a conflict was shown. This has gone with one of the last updates. So this is a serious regression.

Screenshots
n/a

Server details:

  • Nextcloud version: from Version 34.0.x on, currently using 35.0.0
  • PHP Version: 8.4
  • Database: MariaDB 11.8.6
  • OS: Debian 13

Client details:

  • OS: several (Linux, Windows, Android)
  • Browser: several (Firefox, Chrome, Android App)
  • Browser version: n/a
  • Device: n/a

Activity

  1. hede5562 commented on Sep 27, 2026

    @hede5562
    Author

    It's even worse. Downloading the file either via the folder view or even within the editor results in downloading the actual file from the filesystem. NOT the content as the editor shows it. So the editor may show a completely different text than the downloaded file has.

    The folder view does even show the date of the file as is on the filesystem.

    Yet the editor still shows an outdated version from (maybe) its cache?

    If it's not possible to invalidate the cached data in some automated way (like for example with checking if some cache content was modified before the file on disk changed) at least some "invalidate cache" button would be of help here.

  2. airflow2010 commented on Oct 1, 2026

    @airflow2010

    my comment:

    I can acknowledge this problem. This is a very serious issue, because it introduces silent data-corruption, leading to loss of work done, makes it impossible to collaborate on files which are edited both via other ways (like SMB) and access/edits via NextCloud.

    This was introduces recently. Please triage and fix.

    I had an AI-agent look into the issue. I append the findings, perhaps it is helpful.

    AI-agent findings:

    Additional diagnostic evidence from Nextcloud AIO 34.0.4, Text 8.0.0, PostgreSQL, with an external SMB mount, following an upgrade from Nextcloud 33.0.8.

    Read-only investigation confirmed that:

    • An authenticated WebDAV GET returned exactly the same bytes and SHA-256 checksum as the current file on the underlying SMB share.
    • WebDAV PROPFIND returned the correct file ID, modification time and size.
    • Reconstructing the server-side .yjs document together with its stored oc_text_steps produced an older document, missing sections present in the actual file.

    This establishes a divergence between the backing file and Text’s persisted collaborative document, even when Nextcloud’s file metadata is current.

    The following changes appear to explain the regression:

    1. Persisted documents are no longer reset by the cleanup job.

      Commit 0d9bf36 — “fix(cron): do not reset document” (0d9bf36), part of enh/y indexeddb #7621 (enh/y indexeddb #7621), removed resetDocument() from Cleanup::run(). Previously, documents without active sessions could be reset, subject to the unsaved-changes safeguard. The stated intention is to preserve the editing session and baseVersionEtag for returning offline clients.

      However, getOrCreateDocument() (https://github.com/nextcloud/text/blob/v34.0.4/lib/Service/DocumentService.php#L118-L123) reuses an existing document without validating it against the current backing file. ApiService::create() (https://github.com/nextcloud/text/blob/v34.0.4/lib/Service/ApiService.php#L106-L123) then returns the saved .yjs state when available.

      Direct SMB writes do not pass through Nextcloud’s BeforeNodeWrittenEvent/NodeWrittenEvent handling, so the document-reset listener (https://github.com/nextcloud/text/blob/v34.0.4/lib/Listeners/NodeWrittenResetDocumentListener.php#L33-L68) does not provide equivalent invalidation for that write path. Consequently, the persisted editor document can remain stale across reopening.

    2. The polling endpoint no longer detects external changes.

      Commit a51d1e2 — “fix(sync): do not check for conflicts during sync” (a51d1e2), included through the stable34 backport [stable34] fix/no conflicts on sync #9158 ([stable34] fix/no conflicts on sync #9158), removes assertNoOutsideConflict() from ApiService::sync(), together with the outsideChange/HTTP-409 response for that condition.

      This intentionally avoids false conflicts during concurrent saves, as explained in fix/no conflicts on sync #9149 (fix/no conflicts on sync #9149). However, it also removes the polling mechanism that previously detected genuine external changes while an older collaborative document remained loaded.

    3. The remaining save-time conflict is not propagated to the conflict UI by SaveService.

      Server-side protection still exists: DocumentService::autosave() calls assertNoOutsideConflict(), and ApiService::save() can return HTTP 409 with outsideChange.

      But SaveService.save() (https://github.com/nextcloud/text/blob/v34.0.4/src/services/SaveService.ts#L93-L111) explicitly handles 403 and 412, with no equivalent handling for 409. The SAVE_COLLISION handling remains in PollingBackend (https://github.com/nextcloud/text/blob/v34.0.4/src/services/PollingBackend.ts#L206-L215), whose sync request no longer receives this conflict response.

      An isolated test using the installed SaveService source and a mocked 409 response produced no conflict event or user-facing error message from that service. The missing save-side 409 handling also exists in the previously installed version; removing the polling check exposes that existing gap.

    Scope of these findings: The stale editor state was verified against the actual file. No production save/reset was performed, and silent overwriting was not independently reproduced. The code still contains save-time conflict checks, so these findings should not be interpreted as proving that all overwrite protection was removed.

    A fix should validate persisted editor state against the backing file when opening/reconnecting and correctly propagate save-time 409 responses to conflict resolution, while preserving unsaved/offline edits. Regression tests should modify the external storage directly: uploading through Nextcloud exercises its write-event listeners and therefore does not cover the same path.

  3. janpep commented on Oct 4, 2026

    @janpep

    I observed the exact same symptoms as shown in the first post and consider it a bug.
    Initially, a notification appeared indicating a discrepancy with the file stored on disk, offering a choice of which version to open. This notification—which allowed you to choose between the two versions—has disappeared over the last few weeks.
    I updated everything, but that didn't fix the issue.
    Saving to the file system works fine. THAT file should always be opened/read, after all, as the name implies, it is external storage.
    And indeed: Downloading the file does not give the content you see in the editor, but the content of the file, that is stored on the filesystem. (So for the moment that is our workaround to do some things with the file, where content is appended with a script.)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions