Skip to content

Troubleshooting

The control CLI (and the app) reach the daemon over a Unix socket. If a command reports it can’t connect:

  • Confirm the daemon is actually running (systemctl --user status proton-syncd, or check your foreground terminal).
  • Confirm both sides use the same socket path. With no --socket-path, both default to $XDG_RUNTIME_DIR/proton-sync.sock (with an OS-temp fallback). If you started the daemon with a custom --socket-path, pass the same one to proton-sync.

In the desktop app this surfaces as the Unreachable state, which offers “Start proton-syncd” and “View journal”.

Only one daemon per user may run, and only one per root. If startup fails with a lock error, another live daemon already holds a lock — because every daemon shells the same proton-drive CLI, whose shared cache isn’t concurrency-safe. Stop the running daemon. Note that --lockfile-path only isolates the per-root lock; the per-user single-instance lock can’t be bypassed by any flag (for a fully isolated test, run under a separate $XDG_STATE_HOME). The daemon fails to start with a clear error naming the locked lockfile, rather than failing silently.

If uploads, downloads, or listings fail, reproduce the underlying proton-drive call directly to isolate the problem:

Terminal window
proton-drive filesystem list --json /Drive/RemoteFolder

If that fails, fix authentication, permissions, or the remote folder name first — the daemon can only be as healthy as the CLI it shells. Check the daemon’s logs for the structured fields (operation, attempt, exit status, stderr, timeout); see Logging.

Event-driven detection reuses the proton-drive CLI’s keyring session. If the CLI is idle and its token expires, a pass fails auth and is skipped until the CLI refreshes — and the daemon degrades to snapshot scans meanwhile, so sync keeps working, just less cheaply. Keep proton-drive logged in, and keep the desktop keyring unlocked (with DBUS_SESSION_BUS_ADDRESS set) for a service. You can also opt out with --no-events-driven to force snapshot-only detection.

That’s usually the delete-approval guard doing its job: deletions are withheld until approved. Check what’s pending:

Terminal window
proton-sync pending
proton-sync approve <path> # or --all
proton-sync syncnow

If a deletion still doesn’t apply after approval, the entity may have changed since you approved it — approvals are pinned to the exact content/id you saw, so a stale approval is inert. Re-run pending to see the current queue.

Sync behavior looks wrong — inspect safely

Section titled “Sync behavior looks wrong — inspect safely”

Pause the daemon and look at the local folder and the index before resuming. The index lives at <local-root>/.sync/sync_index.db (the .sync directory is ignored by scanning, so it’s never uploaded):

Terminal window
proton-sync pause
sqlite3 <local-root>/.sync/sync_index.db 'select * from file_index order by file_path;'

Read the index read-only while the daemon might run — it has no WAL, so a writer and reader can race. Prefer the .status.json / .metrics.json sidecars (or proton-sync status) for live state.

A new remote folder appeared and started filling up

Section titled “A new remote folder appeared and started filling up”

If you point --remote-root at a path that doesn’t exist, the daemon creates it and uploads your local content into it. A typo therefore silently populates a brand-new folder rather than failing. Always confirm the remote root with proton-drive filesystem list --json <remote-root> first, and preview with --dry-run.

Proton Docs and Sheets are reported as skip_unsupported and left untouched on both sides — the proton-drive CLI can’t download those native types as files. Likewise, symlinks under the local root are skipped in both directions. Neither is an error.