Skip to content

Fix disk I/O error on sync by relocating the database to the App Group container#17

Merged
alexmodrono merged 2 commits into
mainfrom
fix/app-group-database
Jun 1, 2026
Merged

Fix disk I/O error on sync by relocating the database to the App Group container#17
alexmodrono merged 2 commits into
mainfrom
fix/app-group-database

Conversation

@alexmodrono

Copy link
Copy Markdown
Owner

Summary

The 0.2.0 release breaks sync with saveItems step failed: disk I/O error, and the What's New showcase never appears on upgrade. Both are fixed here.

Disk I/O error

The app and File Provider extension kept the live SQLite database inside the File Provider domain's state directory (NSFileProviderManager.stateDirectoryURL()). fileproviderd deletes that directory on every domain remove/re-add — which the app triggers on Sparkle updates, session-expiry recovery, and manual resets. After such an event the app keeps writing through the now-unlinked file handle, so the next sync fails with a disk I/O error. (Confirmed on disk: the running app held open fds to a state-dir database whose entire domain directory had been reclaimed.)

The canonical database (and user-created local file content) now lives in the App Group container, which both processes already reach via the application-groups entitlement and which fileproviderd never reclaims. The handle survives domain resets, so re-registration no longer needs to snapshot and re-seed. The bundled MCP helper also reads live data now instead of a stale snapshot, since it already resolves to the container path.

A one-time migration copies any surviving per-site data from the old state-directory database into the container.

What's New

The previous gate treated an empty last-seen version as a fresh install and suppressed the showcase — but that key is empty for every upgrader too. It now shows whenever the last-seen version differs from the current one (fresh installs included) and stamps the version on dismiss. The sheet is only attached to the workspace, so onboarding is never interrupted.

Testing

  • xcodebuild build (app + extension + MCP): succeeds
  • PersistenceTests + SyncEngineTests: 21 + tests pass, 0 failures

Release

Intended to re-cut the v0.2.0 tag; the CI build number increments so Sparkle still offers the update to anyone on the broken 0.2.0.

The app and File Provider extension kept the live SQLite database inside the File Provider domain's state directory (NSFileProviderManager.stateDirectoryURL). fileproviderd deletes that directory on every domain remove/re-add — which the app triggers on Sparkle updates, session recovery, and manual resets. After such an event the app kept writing through the now-unlinked file handle, so the next sync failed with "saveItems step failed: disk I/O error".

Move the canonical database, and user-created local file content, to the App Group container. Both processes already reach it via the application-groups entitlement and fileproviderd never reclaims it, so the handle stays valid across domain resets and re-registration no longer needs to snapshot and re-seed. The bundled MCP helper now reads live data instead of a stale snapshot, since it already resolves to the container path.

A one-time migration copies any surviving per-site data from the old state-directory database into the container.
The previous check treated an empty last-seen version as a fresh install and recorded the current version without showing the showcase. That key is empty for every upgrader too (earlier versions never wrote it), so the sheet was suppressed for exactly its intended audience. Show it whenever the last-seen version differs from the current one — fresh installs included — and stamp the version on dismiss. The sheet is only attached to the workspace, so onboarding is never interrupted.
@alexmodrono alexmodrono merged commit 13c79df into main Jun 1, 2026
1 check passed
@alexmodrono alexmodrono deleted the fix/app-group-database branch June 1, 2026 21:20
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

Nightly Build

Download Findle Nightly (unsigned)

Built from a591746.

Important

This build is unsigned. macOS will block it on first launch. To open it:

  1. Try to open the app normally — macOS will show a warning and refuse.
  2. Go to System Settings → Privacy & Security, scroll down, and click Open Anyway.
  3. The File Provider extension requires code signing and won't work in this build.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant