Skip to content

JsonCacheInfoRepository: FormatException: Unexpected end of input (at character 1) ^ #450

Open

Description

@gemunet

🐛 Bug Report

occasionally this error is generated when initializing CacheManager with JsonCacheInfoRepository

Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: FormatException: Unexpected end of input (at character 1)

^

       at .jsonDecode(dart:convert)
       at JsonCacheInfoRepository._readFile(json_cache_info_repository.dart:143)
       at JsonCacheInfoRepository.open(json_cache_info_repository.dart:40)
       at new CacheStore.<fn>(cache_store.dart:34)

This happens when the {databaseName}.json file is created but empty and jsonString = ""

JsonCacheInfoRepository.dart: _readFile()
final json = jsonDecode(jsonString) as List<dynamic>;

A possible solution would be to check that the file is not empty before decoding the json

    if (await file.exists() && await file.length() > 0) {
      try {
        final jsonString = await file.readAsString();
        final json = jsonDecode(jsonString) as List<dynamic>;

note: I don't know why the json file is empty and not with an empty list []

Expected behavior

no error

Configuration

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.16.1, on Microsoft Windows [Versi¢n 10.0.22631.3296], locale es-CL)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Build Tools 2022 17.8.2)
[√] Android Studio (version 2022.3)
[√] VS Code (version 1.87.2)
[√] Connected device (4 available)
[√] Network resources

• No issues found!

Version: 3.3.1

Platform:

  • 📱 iOS
  • 🤖 Android 13 (AP I33)

Activity

  1. Migo-17 commented on Oct 3, 2024

    @Migo-17

    Any updates on when this issue will be fixed ?

  2. aazgersky commented on Nov 22, 2024

    @aazgersky

    Faced with same problem on iOS devices
    stack_trace

  3. duocnguyen6799 commented on Feb 21, 2025

    @duocnguyen6799

    Is there any update on this? I'm facing the same issue!

  4. bothyculture commented on Mar 8, 2025

    @bothyculture

    I get this issue a lot too

  5. manoj-simform commented on Jun 5, 2025

    @manoj-simform

    Do we have any update on this?

  6. aazgersky commented on Jun 5, 2025

    @aazgersky

    @bothyculture Why you decided to close your PR? We really need this fix

  7. hayatshin commented on Oct 9, 2025

    @hayatshin

    Same here. any update on this?

  8. HeftyCoder commented on Oct 23, 2025

    @HeftyCoder

    I don't think this is caused when creating the file. Or at least, I haven't gotten the error when creating the .json file. (Note that I am using the JsonCacheInfoRepository.withFile constructor, but I don't think there is a difference).

    I have had this happen when I abruptly closed the app from my IDE and then re-opened it, which somehow caused an existing database file to be emptied completely. I had multiple CacheManagers, but only one at a time active. These were closed and opened when users were logging to different servers.

    I then noticed that despite there being multiple CacheManagers, I had them all with the same cacheKey. Even though only one was active at a time, it seems that this wasn't enough, and probably a race condition was happening where one CacheManager instance corrupted one of the .json files. I made them all have different keys and I have not seen the issue since.

    If you have seen this issue with only one CacheManager, then there is indeed something more serious going on, and I would suggest at least not closing the app abruptly through the IDE. Or you might have forgotten to dispose your CacheManager?

  9. alamin-karno commented on Jul 16, 2026

    @alamin-karno

    We're hitting this too — flutter_cache_manager 3.4.1, Flutter 3.32.5, Android (observed on a Samsung SM-A325F / Android 13, but not device-specific). FormatException: Unexpected end of input (at character 1) from jsonDecode in JsonCacheInfoRepository._readFile, reported via FlutterError.reportError.

    In our case it's a single CacheManager instance/cache key (not the multi-instance race @HeftyCoder described above), so our best guess is the plain, non-atomic writeAsString in _saveFile() — a process kill mid-write leaves a truncated/empty {databaseName}.json, and every subsequent open() re-decodes the same corrupted file until something else happens to overwrite it.

    Since there's no released fix yet, we worked around it on our end by wrapping JsonCacheInfoRepository to validate the index file before opening, and deleting it if it's not valid JSON, so a corrupted file gets discarded instead of persisting across launches:

    class ResilientJsonCacheInfoRepository extends JsonCacheInfoRepository {
      ResilientJsonCacheInfoRepository({required String databaseName})
          : super(databaseName: databaseName);
    
      @override
      Future<bool> open() async {
        await _deleteFileIfCorrupted();
        return super.open();
      }
    
      Future<void> _deleteFileIfCorrupted() async {
        final directory = await getApplicationSupportDirectory();
        final file = File(join(directory.path, '$databaseName.json'));
        if (!await file.exists()) return;
        try {
          final content = await file.readAsString();
          if (content.trim().isEmpty) {
            throw const FormatException('Cache index file is empty');
          }
          jsonDecode(content);
        } catch (_) {
          await file.delete();
        }
      }
    }

    Posting in case it's useful to others as a stopgap. The real fix is presumably making _saveFile() write atomically (temp file + rename) so a killed process can't leave a truncated file in the first place — happy to help if the closed PR mentioned above needs someone to pick it back up.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions