Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FileSystemException: Cannot delete file #335

Closed
jovanovski opened this issue Feb 11, 2020 · 21 comments · Fixed by Baseflow/flutter_cache_manager#185
Closed

FileSystemException: Cannot delete file #335

jovanovski opened this issue Feb 11, 2020 · 21 comments · Fixed by Baseflow/flutter_cache_manager#185
Labels
type: bug Something isn't working up for graps Issues marked with this label are relatively easy problems that are ideal for starting contributors.

Comments

@jovanovski
Copy link

Firebase keeps reporting issues in my app that look like this:

FileSystemException: Cannot delete file, path = '/data/user/0/<PACKAGE>/cache/libCachedImageData/6cbff3e0-301f-11ea-d72d-0335a490e7f0.png' (OS Error: No such file or directory, errno = 2)

Not really sure what causes them, I have a hard time recreating it too.

@Masaokb
Copy link

Masaokb commented Feb 12, 2020

I have the same problem

@jlopezr
Copy link

jlopezr commented Feb 12, 2020

I think that it is related with how flutter_cache_manager manages the cache:

https://pub.dev/packages/flutter_cache_manager#-changelog-tab-

Perhaps it is a good idea to try to upgrade flutter_cache_manager to last version.

@snaeji
Copy link

snaeji commented Feb 14, 2020

I'm having this issue too. My guess is that there is no guarantee that the cache is not cleared by the system. But it is causing a great deal of noise in Crashlytics since every error is unique with the image filename.

@renefloor
Copy link
Collaborator

renefloor commented Feb 21, 2020

That's strange.. The only 2 places where a file is deleted have checks for existence:

    var file = new File(p.join(await filePath, cacheObject.relativePath));
    if (await file.exists()) {
      file.delete();
    }

Which version of cached_network_image are you using?

@renefloor renefloor added status: needs more info We need more information before we can continue work on this issue. type: bug Something isn't working labels Feb 21, 2020
@snaeji
Copy link

snaeji commented Feb 24, 2020

The version I am using is cached_network_image: ^2.0.0.

@Viper-Bit
Copy link

i have the same problem right now, and using cached_network_image 2.0.0

@Surio89
Copy link

Surio89 commented Apr 23, 2020

problem persists in 2.1.0+1

@joknjokn
Copy link

joknjokn commented May 4, 2020

Same problem, both Android and iOS.

@williamtank
Copy link

The problem caused by cache_store.dart ’s _cleanupCache (in flutter_cache_manager-1.2.2)

  Future<void> _cleanupCache() async {
    final toRemove = <int>[];
    final provider = await _cacheInfoRepository;

    final overCapacity = await provider.getObjectsOverCapacity(_capacity);
    for (final cacheObject in overCapacity) {
      unawaited(_removeCachedFile(cacheObject, toRemove));
    }

    final oldObjects = await provider.getOldObjects(_maxAge);
    for (final cacheObject in oldObjects) {
      unawaited(_removeCachedFile(cacheObject, toRemove));
    }

    await provider.deleteAll(toRemove);
  }

overCapactiy and oldObjects are both lists of CacheObject to be deleted. In some cases, one file may be deleted twice, and the _removeCachedFile is an asynchronous function, resulting in a double-delete crash

  Future<void> _removeCachedFile(CacheObject cacheObject, List<int> toRemove) async {
    //  ... more code
    final file = (await fileDir).childFile(cacheObject.relativePath);
    if (await file.exists()) {
      unawaited(file.delete());
    }
  }

@renefloor
Copy link
Collaborator

Nice catch @williamtank.

I guess it should be enough to do the removal inside the if (or revert the if)

Current:

  Future<void> _removeCachedFile(
      CacheObject cacheObject, List<int> toRemove) async {
    if (!toRemove.contains(cacheObject.id)) {
      toRemove.add(cacheObject.id);
      if (_memCache.containsKey(cacheObject.url)) {
        _memCache.remove(cacheObject.url);
      }
      if (_futureCache.containsKey(cacheObject.url)) {
        unawaited(_futureCache.remove(cacheObject.url));
      }
    }
    final file = (await fileDir).childFile(cacheObject.relativePath);
    if (await file.exists()) {
      unawaited(file.delete());
    }
  }

Proposed:

  Future<void> _removeCachedFile(
      CacheObject cacheObject, List<int> toRemove) async {
    if (!toRemove.contains(cacheObject.id)) {
      return;
    }
    toRemove.add(cacheObject.id);
    if (_memCache.containsKey(cacheObject.url)) {
      _memCache.remove(cacheObject.url);
    }
    if (_futureCache.containsKey(cacheObject.url)) {
      unawaited(_futureCache.remove(cacheObject.url));
    }
    final file = (await fileDir).childFile(cacheObject.relativePath);
    if (await file.exists()) {
      unawaited(file.delete());
    }
  }

The async only goes async at the first await.

@renefloor renefloor added up for graps Issues marked with this label are relatively easy problems that are ideal for starting contributors. and removed status: needs more info We need more information before we can continue work on this issue. labels May 15, 2020
@danielgomezrico
Copy link

danielgomezrico commented Jul 6, 2022

Is this already deployed? I see this in version 3.2.1 too and I see that it still uses flutter_cache_manager 3.3.0 inside of it and not the version that had that fixed

@danielgomezrico
Copy link

@renefloor ping

@renefloor
Copy link
Collaborator

@danielgomezrico not sure what fix you are referring to. PR Baseflow/flutter_cache_manager#185 was merged in June 2020 and was released in flutter_cache_manager 1.4.0, so that's already deployed long ago.

You still see a 'cannot delete file' issue?

@danielgomezrico
Copy link

Sorry for my weird message, yeah it is still happening, It's pretty bad because it happens A LOT, we get like 50.000 errors on sentry.io and then our quota for errors on the monitor dies in the first day.

Ideas:

  • The first ocurrence happened after we moved into cached_network_image 3.0.0
  • It started happening a lot after we updated from cached_network_image 3.0.0 to 3.2.1 🤔

It seems to me that it started to break a lot, the stacktrace I get is:

FileSystemException: FileSystemException: Cannot delete file, path = '/var/mobile/Containers/Data/Application/7109841C-AB53-4060-B872-633BFA63D05C/Library/Caches/cacheKey/d5bcf110-fe24-11ec-8224-25b70ed8985a.webp' (OS Error: No such file or directory, errno = 2)
  File "file_impl.dart", line 283, in _File._delete.<fn>
  File "zone.dart", line 1434, in _rootRunUnary
  File "<asynchronous suspension>"
  File "forwarding_file_system_entity.dart", line 66, in ForwardingFileSystemEntity.delete
  File "<asynchronous suspension>"
  File "cache_store.dart", line 190, in CacheStore._removeCachedFile

@renefloor
Copy link
Collaborator

It's weird, that line number doesn't make sense. We do a check just before deleting if it exists. If you can provide a small reproducible example that would be great.

@danielgomezrico
Copy link

danielgomezrico commented Jul 25, 2022

I never got this in my device so I dont have a way to reproduce it easily 🤔

I just saw another stacktrace that looks similar:

Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: FileSystemException: Cannot delete file, path = '/data/user/0/com.lahaus.client/cache/cacheKey/b7f91310-0816-11ed-921c-25198252b0fa.webp' (OS Error: No such file or directory, errno = 2). Error thrown tag(null): message(Not handled error).
       at ._rootRunUnary(.java)
       at ForwardingFileSystemEntity.delete(forwarding_file_system_entity.dart:66)
       at CacheStore._removeCachedFile(cache_store.dart:190)

May be related to not having permissions to read files? We have these permissions on android/Manifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>

@renefloor
Copy link
Collaborator

It shouldn't need external storage, because this data is part of the app storage.

@danielgomezrico
Copy link

Got it and thanks for the warning, we need that for another feature, but I posted just to see if it was related :)

@danielgomezrico
Copy link

@renefloor we reopened the issue here #761, WDYT?

@renefloor
Copy link
Collaborator

Not sure what to do at the moment, it's hard to reproduce and I don't see a reason for this to happen in the code. Might need some big refactoring to get this out of it, but I'll have to study very carefully what makes sense. I don't think this happens at a lot of apps, so maybe it's some combination with how you handle the files in the rest of the app.

@danielgomezrico
Copy link

That sounds cool, should we close that one to reopen this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working up for graps Issues marked with this label are relatively easy problems that are ideal for starting contributors.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants