GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add database integrity check by turekj · Pull Request #407 · Baseflow/flutter_cache_manager

Conversation

@turekj

@turekj turekj commented Apr 14, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

✨ What kind of change does this PR introduce? (Bug fix, feature, docs update...)

This change is in between a bug fix and a new feature.

⤵️ What is the current behavior?

We're currently using flutter_cache_manager through cached_network_image. We observe the following scenario in the crash logs:

SqfliteDatabaseException: DatabaseException(Error Domain=FMDatabase Code=11 "database disk image is malformed" UserInfo={NSLocalizedDescription=database disk image is malformed}) sql 'INSERT INTO cacheObject (url, key, relativePath, eTag, validTill, touched, length) VALUES (?, ?, ?, ?, ?, ?, ?)' args [https://cdn.everskies.com/media/badge/TMiBI9ss1X_c..., https://cdn.everskies.com/media/badge/TMiBI9ss1X_c..., cab86ba0-daab-11ed-ac21-0b56a114789e.png, "791d34fba03a4949d937107eedde8d96", 1682849089370, 1681466689377, 468]
  File "exception_impl.dart", line 11, in wrapDatabaseException
  File "<asynchronous suspension>"
  File "database_mixin.dart", line 392, in SqfliteDatabaseMixin.txnRawInsert.<fn>
  File "<asynchronous suspension>"
  File "basic_lock.dart", line 33, in BasicLock.synchronized
  File "<asynchronous suspension>"
  File "database_mixin.dart", line 344, in SqfliteDatabaseMixin.txnSynchronized
  File "<asynchronous suspension>"
  File "cache_object_provider.dart", line 101, in CacheObjectProvider.insert
  File "<asynchronous suspension>"
  File "cache_store.dart", line 59, in CacheStore.putFile

We can't tell how the DB got corrupted, but we know it happens mostly on iOS devices. This makes sense as according to sqflite docs:

Android and iOS handles corruption in a different way:

  • on iOS, it fails on first access to the database
  • on Android, the existing file is removed.

Why would fixing a DB corruption make sense in the library? The problem is that once the DB gets corrupted, there cache is not functional for the user. All update/insert operations fail and there's no indication that something is wrong when open() is called on the CacheObjectProvider. There's no easy way to recover from this scenario, especially in use cases such as cached_network_image.

🆕 What is the new behavior (if this is a feature change)?

When the db is opened, the additional pragma integrity_check (reference) query is run. If the db is corrupted, it drops the file before the db connection is opened, thus allowing the cache to "recover" from the failed state.

The obvious drawback of this approach is that the binary cache contents are not wiped. I will happily accept pointers on how to resolve this and other potential issues.

💥 Does this PR introduce a breaking change?

No.

🐛 Recommendations for testing

The way I tested this on iOS simulator (on macOS):

  1. Run the example app and cache some files.
  2. Print out the database path and open the DB in Xcode.
  3. Pick Navigate > Reveal in Project Navigator from the top bar.
  4. Right-click the file and pick Open As > Hex File.
  5. Scroll down till you can see relative paths of the cached files.
  6. Select and delete the hex values from the middle of one row to the middle of another row.
  7. Save the db file (it's now corrupted).
  8. Re-run the app.

At point 8. the library with no patch applied will stop caching any files.

📝 Links to relevant issues/docs

  • sqflite on handling corruption - docs
  • pragma integrity_check from SQLite - docs
  • Sample stacktrace we're observing:

🤔 Checklist before submitting

  • All projects build
  • Follows style guide lines (code style guide)
  • Relevant documentation was updated
  • Rebased onto current develop

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
turekj added 3 commits April 14, 2023 12:15
@turekj
Add database integrity check
4f6e76c
@turekj
Catch DatabaseException
190b8de
@turekj
Merge branch 'develop' of github.com:Baseflow/flutter_cache_manager i…
457a54d
…nto corrupted-db
contactjavas added a commit to tentram/flutter_cache_manager that referenced this pull request Sep 18, 2023
@contactjavas
drop corrupted db (PR by @turekj: Baseflow#407)
b6ec07d
@martijn00
Merge branch 'develop' into corrupted-db
ab24c71
@rickdijk
rickdijk changed the base branch from develop to main September 16, 2026 00:25
@rickdijk @claude
Merge main into corrupted-db
ee28b5e
cache_object_provider.dart conflicted only with main's format pass
(cce9a65). Took main's formatting and re-applied this branch's change.

Co-Authored-By: Claude <[email protected]>
@rickdijk

rickdijk commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

main has moved since you opened this, and our changes to cache_object_provider.dart left it conflicting. I have merged main into your branch and resolved those conflicts. Your change itself is untouched. Once CI runs, flutter analyze will flag the unused e in on DatabaseException catch (e); changing it to on DatabaseException { clears that.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

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

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@turekj @rickdijk @martijn00
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.