{"record":{"id":"75be7c2b1c316318","repo":"benbjohnson/litestream","slug":"temp-file-not-tracked","errorCode":null,"errorMessage":"temp file not tracked","messagePattern":"temp file not tracked","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"vfs.go","lineNumber":517,"sourceCode":"}\n\nfunc openFlagToOSFlag(flag sqlite3vfs.OpenFlag) int {\n\tvar v int\n\tif flag&sqlite3vfs.OpenReadWrite != 0 {\n\t\tv |= os.O_RDWR\n\t} else if flag&sqlite3vfs.OpenReadOnly != 0 {\n\t\tv |= os.O_RDONLY\n\t}\n\tif flag&sqlite3vfs.OpenCreate != 0 {\n\t\tv |= os.O_CREATE\n\t}\n\tif flag&sqlite3vfs.OpenExclusive != 0 {\n\t\tv |= os.O_EXCL\n\t}\n\treturn v\n}\n\nvar errTempFileNotFound = fmt.Errorf(\"temp file not tracked\")\n\n// localTempFile fulfills sqlite3vfs.File solely for SQLite temp & transient files.\n// These files stay on the local filesystem and optionally delete themselves\n// when SQLite closes them (DeleteOnClose flag).\ntype localTempFile struct {\n\tf             *os.File\n\tdeleteOnClose bool\n\tlockType      atomic.Int32\n\tonClose       func()\n}\n\nfunc newLocalTempFile(f *os.File, deleteOnClose bool, onClose func()) *localTempFile {\n\treturn &localTempFile{f: f, deleteOnClose: deleteOnClose, onClose: onClose}\n}\n\nfunc (tf *localTempFile) Close() error {\n\terr := tf.f.Close()\n\tif tf.deleteOnClose {","sourceCodeStart":499,"sourceCodeEnd":535,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L499-L535","documentation":"errTempFileNotFound is the sentinel error indicating a requested temp file name is not present in the VFS's in-memory temp-file registry. Delete translates it into the opaque 'cannot delete vfs file' error, and the Delete/deleteTempFile path returns it when the name is tracked-format (temp-style name) but no corresponding tracked temp file entry exists.","triggerScenarios":"xDelete on a temp-style name that was never opened via this VFS, was already deleted (registry entry removed, e.g. by DeleteOnClose), or after a restart when the registry is empty; also from deleteTempFile's cleanup path when a lookup misses.","commonSituations":"Double-delete of the same temp journal; connection closed with DeleteOnClose removing the mapping before SQLite issues xDelete; multiple VFS instances where the file was opened on a different instance.","solutions":["Ensure the same VFS instance performs open and delete; avoid recreating the VFS between operations.","Treat the file as already gone if DeleteOnClose removed it; check the registry presence before deleting programmatically.","Remove the underlying local file directly (its hashed temp path) if you only need the bytes gone.","If this recurs under normal SQLite operation, report it — SQLite should only delete files it opened."],"exampleFix":"// before\ndb.Close()\nvfs.Delete(name, false) // already untracked by DeleteOnClose\n\n// after\ndb.Close() // DeleteOnClose already removed the temp file; skip manual delete","handlingStrategy":"try-catch","validationCode":"// check registry membership before delete, if the API exposes it\nif !vfs.TracksTempFile(name) { return nil }","typeGuard":null,"tryCatchPattern":"if errors.Is(err, errTempFileNotFound) || strings.Contains(err.Error(), \"cannot delete vfs file\") {\n    // treat as already-deleted; optionally os.Remove local temp path\n}","preventionTips":["Never double-delete temp journal names.","Use DeleteOnClose consistently instead of manual deletes.","Keep open/delete on the same VFS instance.","After restarts, don't reuse stale file references."],"tags":["go","vfs","registry","file-delete"],"backgroundTag":"file-not-found","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}