syncthing: File restore doesn't work on one folder

It works on other directories but on one specific folder there’s no tree displayed, the JS console says:

TypeError: $scope.restoreVersions.tree.filterNodes is not a function
    at syncthingController.js:1967
    at Object.$watchCollectionAction [as fn] (angular.js:11724)
    at Scope.$digest (angular.js:11827)
    at Scope.$apply (angular.js:12080)
    at done (angular.js:7862)
    at completeRequest (angular.js:8045)
    at XMLHttpRequest.xhr.onreadystatechange (angular.js:8001)

Syncthing Version: v0.14.44-rc.3 OS Version: Debian 9.3 Browser Version: Version 64.0.3282.119 (Official Build) beta (64-bit)

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 32 (21 by maintainers)

Commits related to this issue

Most upvoted comments

Take off, nuke from orbit, and rewrite the GUI in Dart or React or something.

I have the same issue and spent quite a bit of time debugging until I found the cause. The problem/bug is in the order of execution in which asynchronous events are fired and executed (timing). I’m not sure why it happens on some machines but not others. In my case it started when my version tree got big (> 5000 versions).

Here’s the run down:

When the user clicks on the Versions button, $scope.restoreVersions.show is invoked and performs the following:

  1. Show the ‘#restoreVersions’ modal/dialog box.
  2. Perform HTTP Get request to fetch the versions. 2a. When the version data is returned assign it to $scope.restoreVersions.versions = data; 2b. Setting $scope.restoreVersions.versions = data; triggers an Angular event to add #restoreTree to the DOM: here
  3. When the top 2 promises are resolved: 3a. Initialize the tree $("#restoreTree").fancytree({}) 3b. Initialize the filters and other stuff.

The issue is that sometimes 3a is being executed before 2b. In other words the initialization of #restoreTree node is called before Angular event is fired to add #restoreTree node to the DOM.

The right fix is to wait until Angular event 2b is fired and completed before performing 3. A quick fix/test/hack is to replace the line here with the following code to essentially wait until #restoreTree is added to the DOM before initializing it:

var waitForRestoreTree = $q.defer();
var waitTimer = setInterval( ()=>{
    if ($("#restoreTree").length){
        clearInterval(waitTimer);
	waitForRestoreTree.resolve();
    }     
}, 100);

$q.all([dataReceived, modalShown.promise, waitForRestoreTree.promise]).then(function() {
...

@rkfg @AudriusButkevicius : This bug is very difficult to replicate since the order of execution in which asynchronous promises and events are not guaranteed to always occur in the same order. Nevertheless, this bug is a legitimate issue and should be re-opened. Thanks

I say there is no point in keeping something open if there is no reproducer, as it’s not something we can fix, hence it’s not actionable task we can close in the future