Lock denied or stuck

The TVO-LOCK family.

Written By Dustin

Last updated 17 minutes ago

TVO-LOCK-* covers an already-held lock, a land or push refused on an exclusive-lockable path, and a path that is not declared lockable.

Already held

TVO-LOCK-001, and the error names the holder and the expiry.

tovio locks

Ask the holder first. A lock exists because concurrent edits to that file destroy work โ€” breaking it does not make the file mergeable.

Note that tovio locks is your local last-known view, and expired locks are dropped as it reads. For what the Forge actually holds right now:

tovio forge lock list --remote <host:port>

Land refused on a diverged binary

TVO-LOCK-002 is not about who holds a lock โ€” it is holder-agnostic. It fires when an exclusive-lockable path was edited divergently on both sides. Because a binary cannot merge, the later write would be silently lost, so the operation is refused instead of producing a conflict object. The same gate applies to a rewrite cascade โ€” change rebase, split, absorb.

The fix is to serialize: keep one sideโ€™s version, re-land, and have the other writer re-apply their edit under an exclusive lock.

Stuck with no holder available

tovio forge lock break <path> --remote <host:port>

An administrative action, gated server-side on role=forge-admin โ€” a non-admin gets a clean 403 and nothing changes. It is recorded in the audit chain, attributed to you, and the prior holder is notified.

Path not declared lockable

TVO-LOCK-003. Locking is opt-in per path: policy declares which patterns are lockable and whether they are exclusive or advisory. If the path is not declared, the repository has not configured it โ€” a configuration question for whoever administers it, not something you can force locally.

Every lock already has an expiry

tovio lock <path> --ttl 2h --exclusive

--ttl is required โ€” there is no way to take a lock without one, and an expired lock auto-releases. So a "stuck" lock is either genuinely still live, or the holder keeps renewing it. Prefer a short TTL you renew over a long one that outlives its purpose. Omit both --exclusive and --advisory to take whichever kind policy declares for the path.

A limitation worth knowing

A Forge arbitrates lock grants, but no push or land path consults a lock store or checks the holder. A lock coordinates; it does not hard-block another identityโ€™s write. Plan around that rather than relying on enforcement that is not there yet.

Reporting it

The code, and whether the path is exclusive or advisory. Not the path, and not the holderโ€™s identity.