SQLite.swift
SQLite.swift copied to clipboard
fatal error : disk I/O error (SQLITE_IOERR_VNODE)
Hi, I have used stephencelis/SQLite.swift in our ios app developed in swift2. We are using this for sync since it is offline app. I am getting this error continuously since last 5 days. DB works well in first user login, when user logs out and login again and try to access db in the app fro any select / update / any db transaction, it crashes with the below error. On logout, we delete the sqlite file in document folder and on new login it recreates. Also, I gete database is locked error in between. Please help.
fatal error: 'try!' expression unexpectedly raised an error: disk I/O error: file /Library/Caches/com.apple.xbs/Sources/swiftlang_swift_2_2/swiftlang_swift_2_2-800.10.13/src/swift/stdlib/public/core/ErrorType.swift, line 54
???????
Well a little bit more information or code where the exception raises would increase the chance to get help.
I faced similar problem in swift 3 after removal and recreation of sqlite file:
2017-10-20 19:18:18.680950 [311:39889] [INFO] {}[Database]: statement aborts at 20: [SELECT * FROM "season" WHERE (("deleted_at" IS ?) AND ("selected_by_user" = ?)) LIMIT 1] disk I/O error (Code 6922)
fatal error: 'try!' expression unexpectedly raised an error: disk I/O error (code: 10): file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-802.0.53/src/swift/stdlib/public/core/ErrorType.swift, line 182
2017-10-20 19:18:18.684283 fatal error: 'try!' expression unexpectedly raised an error: disk I/O error (code: 10): file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-802.0.53/src/swift/stdlib/public/core/ErrorType.swift, line 182 (lldb)
What information or code can be useful to you?
Did you created the database file?
You could post some code. Seems like try!
raises an error because there is no database file.
It seems like database was successfully recreated because after its recreation we get few requests one by one - and the first of them are successfully performed.
Here's the code that falls:
func findSelectedByUser() throws -> DatabaseSeason? {
let dbSeason = SeasonTable.table()
.filter(SeasonTable.Column.deletedAt() == nil && SeasonTable.Column.selectedByUser() == 1)
.limit(1)
for row in try db.prepare(dbSeason) {
if let season = SeasonDatabaseMapper().parseSingle(row: row) {
return season
}
}
return nil
}
Crash appears in db.prepare(dbSeason). Here's the code in which we create the database by user login:
private func connection() -> Connection {
guard let dir = NSSearchPathForDirectoriesInDomains(.documentDirectory,
.userDomainMask,
true).first else {
fatalError("Can't reach documents directory")
}
if let savedUser = UserDefaults.standard.string(forKey: "current_user_email") {
databaseName = "\(savedUser).sqlite"
} else {
databaseName = "db0.sqlite"
}
let path = "\(dir)/\(databaseName)"
log { path }
guard let db = try? Connection(path) else {
fatalError("Can't connect to database")
}
db.trace { message in
log { message }
}
do {
let manager = SQLiteMigrationManager(db: db, bundle: migrationsBundle())
if !manager.hasMigrationsTable() {
try manager.createMigrationsTable()
}
if manager.needsMigration() {
try manager.migrateDatabase()
}
} catch {
fatalError("Can't create database structure: " + error.localizedDescription)
}
return db
}
Is there any other details that can be useful?
Could you try to run a custom sql function instead of filtering on dbSeason
? Just to see if you get what you want when working with sql.
https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#custom-sql-functions
let stmt = try db.prepare("SELECT * FROM table WHERE ...")
I got the same error and it only showed up on my actual device and not in the simulator. The reason for the error was the location of the database file.
See solution here:
I tried to change database's location but still getting the error. @Bjorninn1 Have you encountered this problem again?
FWIW, some notes from my researching this 6922 extended error code. My iOS app gets this error sometimes while using a SQLite database read-only that is stored in the app bundle. It seems more frequent with iOS 13.
6922 is not a standard SQLite extended error. It's added by Apple and corresponds to SQLITE_IOERR_VNODE
.
A Stack Overflow question asking about this same error is: https://stackoverflow.com/questions/43349189/what-does-sqlite-ioerr-vnode-mean
and that leads to the most definitive answer I could find, from the SQLite author at http://sqlite.1065341.n5.nabble.com/What-does-SQLITE-IOERR-VNODE-mean-td95250.html
SQLITE_IOERR_VNODE is an error code used by proprietary modifications to SQLite implemented by Apple for use on MacOS and iOS. I am told "The code indicates that a file relevant to the call was invalidated by a dispatch vnode source event" but I do not understand what that means.
Further speculation about that post is here: http://sqlite.1065341.n5.nabble.com/What-does-SQLITE-IOERR-VNODE-mean-tp95250p95255.html
TL;DR: It's some weird MacOS Virtual Node thing to do with memory-mapped files and "shouldn't be happening"...
This set of Apple slides, https://devstreaming-cdn.apple.com/videos/wwdc/2016/242vdhuk4hmwrxnb465/242/242_whats_new_in_core_data.pdf, referenced in the comments of the SO post above, has a slide with:
Perhaps someone with more than my (minimal!) Apple knowledge can speculate on the trigger conditions for this error and how to avoid them...
I read all the above. I don't mean to be overly negative, but it does seem that error 10 means you're dead in the water. The above comments are not encouraging, and there's no rhyme or reason for the error to appear. It continues for 5 app restarts, then suddenly, we're not doing error 10 any more and everything is fine. And then the next day, it's error 10 again. I've followed the documentation to the letter and ensured the threading is handled correctly. Would love to hear any practical advice other than giving up.
I was able to workaround it by statically linking SQLite. See https://stackoverflow.com/questions/43349189/what-does-sqlite-ioerr-vnode-code-6922-mean/58668058
@simonfoxguitar this started happening much more for me with ios13 and/or Xcode 11. See above.
@simonfoxguitar also see the idea of adding the setting SQLITE_ENABLE_FILE_ASSERTIONS=1
to get more debug info. If you find something, please report back! I lost interest once static linking worked, but it would be nice to remove it from my workspace.
Thanks Mikemee, thanks for the help, I'll give it some effort before giving up. I have that library statically linked, will let you all know how it goes.
Also - did this problem only occur on simulators, or is it across real devices too? Many thanks, appreciate the help greatly.
Both simulator and a real device.