Docs

Errors and recovery

Every JSON-RPC error the daemon or lvcs mcp answers carries data with a reason, a recover kind, and, unless recover is none, the one next step to take; a refusal by a rule names the rule. lvcs explain <value> prints any entry on this page, offline.

Error codes

What went wrong with a request, as the JSON-RPC error's code (its number) and message. Every error's data also says how to recover (a recover value) and, unless that is none, the one next action to take.

parse_error

The request line is not JSON, or not UTF-8 text. Send one JSON object per line.

Number -32700, message "parse error". Recover: fix_request.

invalid_request

The line is JSON but not a JSON-RPC 2.0 request: it lacks jsonrpc, method, or id, or is longer than the daemon reads.

Number -32600, message "invalid request". Recover: fix_request.

method_not_found

No operation has this name. The op vocabulary lists every operation.

Number -32601, message "method not found". Recover: fix_request, none.

invalid_params

The operation exists, but its params don't fit it: a field is missing, has the wrong type, or is out of range.

Number -32602, message "invalid params". Recover: fix_request.

internal_error

The daemon failed to finish the request. A transient fault (a part of the daemon not yet running, a document that failed to load) clears on a retry; a daemon bug does not.

Number -32603, message "internal error". Recover: retry_after, none.

no_participant

The connection has not said which participant it acts for: the first request on a connection must be hello, with a participant this daemon knows and the connecting OS user may act as.

Number -32001, message "no participant". Recover: join, fix_request.

unknown_base

The request is based on a version of the document this daemon doesn't have. Read the document again and redo the change from what it holds now.

Number -32002, message "unknown base". Recover: rebase.

out_of_bounds

A change reaches past the end of the document at the version it is based on. Read the document again and redo the change from what it holds now.

Number -32003, message "out of bounds". Recover: rebase.

rejected

A rule refused the request: the error's rule names which one, and its recovery is that rule's.

Number -32004, message "rejected". Recover: ask, renew, fix_request, wait, fork, none, rebase.

rate_limited

The participant sent requests faster than its rate allows. Wait the time the error gives, then send the same request again.

Number -32005, message "rate limited". Recover: retry_after.

secret_detected

The change looks like it holds a secret (a key, a token, a password), so it was held and not shared. Confirm it holds none, or change the request so it doesn't.

Number -32006, message "secret detected". Recover: confirm, fix_request.

path_collision

The path collides with another one that differs only by letter case or Unicode normalization, or names an existing directory. Choose another path.

Number -32007, message "path collision". Recover: fix_request.

Rules

Which rule refused a request: the error's data.rule, present exactly when its code is rejected. Each rule has one recovery.

out_of_scope

No grant the participant holds covers this path or operation.

Recover: ask.

grant_ended

The grant that covered the request has expired or was revoked.

Recover: renew.

quota_spent

The participant has used up the number of changes its grant allows.

Recover: renew.

protected_path

The path is protected: a change to it reaches others only after checks pass and a holder of the approve capability approves it.

Recover: fix_request.

unattested

The version the request names has not passed the project's checks yet.

Recover: wait.

policy_unknown

The project's rules for this path are not known yet on this daemon, because its grants have not synced.

Recover: wait.

workspace_refused

The workspace can't take the request: this daemon doesn't run it, or its base refused the merge-back.

Recover: fork.

not_synced

The path is never shared: a control document under .lvcs/, a path the project never syncs (a .gitignore or .lvcsignore ignores it, or it is never-sync), a link or special file on the path, or a path outside every mirrored directory.

Recover: fix_request.

not_author

Only the participant whose change is held may do this.

Recover: ask.

mirror_author

The mirrored directory writes as another participant, so this participant may not write through it.

Recover: fork.

not_a_repository

The project directory is not a git repository, so there is nothing to write a checkpoint into.

Recover: none.

outcome_unknown

An earlier request with the same request id is still running or its answer was lost, so whether it applied is unknown. Read the document again and redo the change from what it holds now.

Recover: rebase.

no_action

run names no gated action: no approved [[actions]] entry in lvcs.toml with on = "manual" or on = { channel = ... } has that name (a change action runs on every merge into main, never by run). Run an action the approved lvcs.toml gates, or add one and have its lvcs.toml change approved first.

Recover: fix_request.

not_eligible

The frontier run names can't be run on by this action yet: its after channel doesn't hold it, and the action's channel holds no passed run of it; or no frontier was named and the after channel holds none, or several. Read the after channel to see which frontiers it holds, then wait for this one or name one it holds.

Recover: wait.

superseded

The frontier run names is behind the action's channel: the channel's value is a newer frontier that holds all of it, and the channel never passed a run of it, so running it would move the channel backward. Read the channel and run the action on its value or a newer frontier; a rollback names a frontier the channel passed before.

Recover: fix_request.

git_rewrite

A mapped git branch was rewritten outside LVCS (a force-push or a reset): its head doesn't descend from the last commit LVCS knew there, so nothing is imported and LVCS moves the branch no more until it does. Restore the branch with the git update-ref the refusal's next names, or merge the rewrite onto that commit.

Recover: fix_request.

action_refused

The approval would put in force a set of actions that is refused: two declarations of one action, a GitHub workflow job LVCS can't run, or an lvcs.toml whose channel triggers name an unknown channel or form a cycle, which the reason names (reason names the action_refusal value). Fix the file, or list the job in lvcs.toml's [workflows] skip, as the reason says, and approve again.

Recover: fix_request.

stale_overlap

A mirror save or an edit was made from an older version of the file than the one it now holds, and the lines it changes overlap lines another participant changed since that version. It was not taken, and the file now holds the current version: read it again and redo the change from what it holds now. The reason names the overlapping lines and who changed them.

Recover: rebase.

device_scope

A paired device may not do this: a read device only reads, a write device also coordinates (asks, answers, holds, says, runs gated actions), and no device edits files or workspaces. Pair a device with the scope it needs (lvcs auth login --write), or do it from an agent or the CLI.

Recover: fix_request.

Recovery kinds

How to recover from an error: the error's data.recover. Unless it is none, the error's data.next holds one concrete action that does it: an operation with its params, the same request sent again, or an lvcs command line.

wait

Wait for something outside the caller to change (an attestation, a sync, a holder releasing a range), then try again.

retry_after

Send the same request again after the time the error gives, in data.retry_after_ms.

rebase

Read the document again and redo the change from what it holds now.

ask

Ask a participant who can allow it: the owner, or the issuer of the grant the request needs; for a peer whose release is older than this daemon's, its owner to upgrade.

yield

Leave the range to the participant working on it, and work elsewhere.

confirm

Confirm the request is what was meant, and it goes ahead.

renew

Get the grant renewed, or a new grant, from its issuer.

fork

Work in a forked workspace of your own instead, and merge it back later.

join

Join the project as a participant first.

fix_request

Change the request itself: its parameters, its path, or its operation.

upgrade

An LVCS-owned file under .lvcs/ has a newer format than this lvcs reads, or a peer speaks a newer wire major than this daemon: install a newer lvcs, then run the command again.

migrate

An LVCS-owned file under .lvcs/ has an older format, or none (written before format headers): run lvcs migrate in the project root with no daemon running, then run the command again.

none

Nothing the caller can do changes the answer.

Notification kinds

Kinds of notification: a notification's kind. A notification names who sent it, where, and when, never what they wrote; read its content with notifications.read.

announce

Another participant announced it is about to change, or has just changed, a range of a file.

hold

Another participant objected to your announced change: your edit waits, and a thread on the range holds their reason.

note

Another participant answered your announced change with information only; your edit goes ahead.

ask

Another participant asked you a question in a thread, which stays open until it is answered.

answer

Another participant answered a question you asked.

say

Another participant added a message to a thread you are in, with no reply expected.

stale_save

A save of yours to a mirrored file was applied on an older version of the file than the one it replaced, so others' changes between them may be merged into it.

refused_save

A save of yours to a mirrored file was refused and not shared; its content says which rule refused it and how to recover.

write_held

The mirror could not write a file you author because another program held it open or denied access to it (Windows), and stopped trying after its deadline: the file on disk is older than its document. Close the file in the program holding it; the next render writes it.

action_failed

An action failed at a frontier, and you changed a file it reads since the frontier where it last passed: one per action and failing streak. It names the action, both frontiers, the lines you changed, and the window's other authors; its content is the failing output's tail. Fix the change, then the next passing frontier sends an action_succeeded.

action_succeeded

An action that failed after your change passes again at a later frontier, which ends its failing streak.

derived_superseded

Your version of a derived (generated) file is not the one shown: another participant's version of it was chosen, so yours is hidden.

derivation_failed

A generator failed, or runners disagreed on its output, on inputs you changed since its last counted generation: one per derivation, a newer one replacing it. Its content names the generated file to run lvcs explain on, which shows the generator and the failure; fix the inputs.

incompatible_peer

A peer of the project runs a release whose wire major version differs from this daemon's, or speaks no sync protocol this daemon does, so nothing syncs with it: one per peer and daemon run. Its content names the peer, both versions, and who upgrades: you (upgrade) when the peer's is newer, else the peer's owner (ask). lvcs status lists the peer too.

git_import

Commits made outside LVCS on a mapped git branch were imported onto main, or a rewrite of the branch was refused: it names the branch and the head; its content lists each commit (id, author, subject) and each path written or skipped and why. A rewrite's error says how to restore the branch; a path skipped for a conflict is redone by hand (rebase).

protected_held

A change to a protected path by a participant who doesn't hold Approve on it is held, while the approved lvcs.toml declares no change action: to the owner and each Approve holder this daemon holds, once per path and held heads. It names the path; its content names who wrote it. Your own edit of the path built on the held change approves it, so read the held change first (read at main shows it).

issue_claimed

Another participant took an issue, or a plan task, assigned to you, after you were not present on the issue for ISSUE_PRESENCE_SECS. It names the issue, the task, and who took it; lvcs issue view shows the issue.

claim_held

Your claim on an issue or task was held by its assignee, who is working on it now; its content is their reason.

issue_fixed

An issue you created or are assigned is fixed: its done channel holds a frontier with all its linked work, and its plan is done.

issue_reopened

An issue you created or are assigned that was fixed is open again: its done channel moved to a frontier without its linked work (a rollback, decision 304).

Derived rules

Which rule made a file derived or not, in the order the classifier tries them; the first that applies wins. A vocabulary for lvcs status and lvcs explain <path>, never a telemetry attribute value.

gitattributes

A .gitattributes line decided: a negation (-linguist-generated, linguist-generated=false, -lvcs-derived, lvcs-derived=false) makes the file not derived, and is tried first; a positive attribute (linguist-generated, linguist-generated=true, lvcs-derived) makes it derived, and is tried after lvcs_toml.

lvcs_toml

A the generator's writes pattern in lvcs.toml at its approved heads decided, tried after a .gitattributes negation: a pattern makes the file derived, and a ! pattern makes it not derived.

pattern

The path matches DERIVED_PATTERNS, tried after every .gitattributes and lvcs.toml rule.

marker

One of DERIVED_MARKERS is in the file's header, tried last.

none

No rule makes the file derived, or the path is in NEVER_DERIVED, which is checked before every other rule.