When an operation is interrupted

Computers crash, laptops run out of battery, and disks fill up. Synck is built so that an interruption at any moment leaves the repository in one of two states: the operation either did not happen, or it can be finished. You should never end up with half a commit, or with history that refers to content that is not there.

This page explains how that works, and what, if anything, you need to do.

The one rule

Leave .synck alone, and run Synck again. Do not delete files in .synck, restore an older copy of it on top, or “clean up” its temporary directories. Synck keeps the records it needs to recover in there.

Two stages: content first, then history

Every write follows the same order:

 1. store new content         objects written and flushed to disk
          │
          ▼
 2. accept the commit         one database transaction: the point of no return
          │
          ▼
 3. bring indexes up to date  repository order, current-state tables, history index
  • Interrupted during stage 1: nothing is in the history. At worst some stored objects are not referenced by anything. They are harmless and synck gc can remove them. History can never point at content that is not there, because content is always stored first.
  • Interrupted during stage 2: the database transaction either committed or it did not. There is no partial commit.
  • Interrupted during stage 3: the commit is accepted and permanently in the history. Only the bookkeeping after it is pending.

Repositories with a checkout

In a repository with a checkout, recovery is automatic. Operations that change both the history and your files, such as mv, revert, recover, restore-tree, commit --batch and changes to a checkout’s selection, first write an intent record in .synck that describes exactly what they are going to do. If one is interrupted, the next Synck command you run in that repository finds the record, finishes the operation, and then does what you asked:

$ synck status          # first command after a crash
nothing to commit, working tree clean

If the state on disk does not match any valid point of the interrupted operation, for example because files were changed by hand in the meantime, Synck does not guess. It stops and reports exactly what is inconsistent. Resolve that, or restore from a backup, before continuing.

Batch commits

synck commit --batch records several commits. If it is interrupted, the commits that were already accepted stay accepted. Synck continues forward. It never pretends to roll accepted commits back. The batch resumes automatically on the next command. If you changed one of its remaining files in the meantime, it finishes the accepted part and leaves the rest as ordinary uncommitted changes.

When an interrupted command prints commit IDs before its error, those commits are in the history. Check synck log before you try anything again.

Writes with synck repository

The synck repository write commands, such as save-file and append-chat, recover only when you ask. Reading a repository never changes it, so a write that was interrupted in stage 3 stays pending until you finish it:

$ synck repository save-file 01a174b7-8f4e-76f1-8ac4-440db922fb52 proposal-v3.txt --path launch-continued
synck: commit sha256:2776…edf1 was accepted; local recovery is pending: ...
$ synck repository finalize launch-continued
{"finalized":"launch-continued","schema_version":1}

Do not run the original command again. It would record the change a second time, as a duplicate file version or a duplicate message. Until you finalize, synck repository verify reports that sequencing is incomplete.

Copies and archives

synck archive, synck repository archive, synck repository import and the export commands all write to a new destination. They build the result privately and publish it only once it is complete and verified:

  • Interrupted before publishing: the destination does not exist. A killed process may leave a private staging directory beside it, with a name starting with .synck-. It is safe to delete. Synck never resumes from it.
  • Published, but the final flush to disk failed: Synck reports this case explicitly. The result is visible but might not survive a crash. Verify it, and repeat the copy to a new destination if in doubt. Do not assume nothing was created.

The source is never modified by a copy, so a failed copy leaves your previous copies exactly as they were.

“Repository busy”

Each Synck command holds an exclusive lock on the repository while it runs. A second command started at the same time fails immediately rather than waiting:

synck: repository busy

This is not damage. Wait for the other command to finish (it may be a script, an editor integration or another terminal) and try again. If you are sure no other Synck process is running, the lock was released when the previous process ended. Locks do not survive their process, so there is nothing to delete.

Disk full

Running out of space is just another interruption. The operation stops at one of the stages above and recovers the same way. Free some space, then run the next command or finalize. Do not free space by deleting files in .synck. To find out what history is costing you, use synck storage.