Recover from a HALTED latch
Find out why native calls stopped, read the ledger and the faulted call's records, and clear what the runtime checks.
When the supervision of a native call goes wrong, the runtime writes a latch file and refuses every later native call until you resolve it. The checks are in crates/lema-check/src/lib.rs.
Before you start
- Access, as the operator, to the runtime configuration and the paths it names. Below,
OUTis the configuration’soutput,LOCKitsshared_lock, and$CONFIGthe configuration file.
Steps
-
Find which latch is set:
Shell cat "$OUT/HALTED" "$LOCK.HALTED"Latch Written when Stops native calls of OUT/HALTEDa call’s supervision fails, for example a timeout, a log over 16 MiB, incomplete output capture, a process that could not be cleaned up, or the distribution changing during the call every configuration with this outputLOCK.HALTEDa call’s systemd scope could not be confirmed gone after it ended every configuration with this shared_lockEach latch holds one line,
<call name>: <fault>. Refused calls fail withnative calls halted; see …/HALTEDornative calls halted host-wide; see ….HALTED. A failed proof is not a fault: Lean exiting with an error is reported and sets no latch.While a latch is set,
lema servestill answers requests that make no native call, such asinfo,find,showandalias. Anything that needs a native call is refused, andlema check-runtimeexits 1. -
Read the ledger.
OUT/ledger.jsonlhas one JSON line per event:reservebefore each call (name,unit,config_sha256,at,host) andcompleteafter it (name,fault,exit_code,wall_seconds,at). List the faulted calls:Shell grep '"event":"complete"' "$OUT/ledger.jsonl" | grep -v '"fault":null'A
reservewith no latercompletefor the same name is an unresolved call, for example afterlema servewas killed during a call. It stops later calls too, without a latch:unresolved native calls in the ledger: […]. -
Read the faulted call’s records in
OUT:<name>-reserved.json: the command line, working directory, time limit and start time;<name>-result.json: the same, plus the process ID, exit code, wall time, fault, log size and end time;<name>.log: the call’s output;work/<name>/: its work directory.
-
For a host-wide latch, make sure the scope is gone. The latch text names the unit (
native scope cleanup incomplete: lema-native-….scope …). Every native call also refuses while such a scope is live (a native scope is still present). This is the listing the runtime checks, and units shown as inactive or failed do not count:Shell systemctl --user list-units --all --no-legend --plain 'lema-native-*' -
Resolve the latch.
For a latch in
OUT, the simplest way is a fresh output. Write a configuration with a newoutput(Write a runtime configuration), restartlema servewith it, and keep the latched output as the record of the fault. The new output starts with an empty module cache.To keep using the same output, two things must be true. Neither latch file may exist. Every faulted or unresolved call in the ledger must have a later line
{"event":"resolved","name":"<call name>"}. Nolemacommand writes that line or removes a latch: both are left to you. Every ledger line must be areserve,completeorresolvedevent. Any other line makes every later native call fail, andinfotoo (ledger entry …).For a host-wide latch, a fresh output does not help: every configuration that shares the lock is stopped until
LOCK.HALTEDis gone. -
Confirm that native calls run again:
Shell lema check-runtime --runtime $CONFIGIt makes one small native call in that configuration’s output. It exits 0 when the call ran, 75 when the lock is busy or the host is loaded, and 1 for any other refusal.
Written against lema-lang at commit 5a94951, 17 Oct 2026.