Saphan StudioDocs
Troubleshooting

The record and gates

Refusals about the workspace, the decisions written into it, and the teardown that closes a piece of work.

37 classes. 2 explained, 35 named only.

A gate is a point where a decision is written down and signed. The record is where it is written. Refusals in this family are almost always one of: the product could not work out which workspace or stream you meant, or the decision you asked to write would not survive being read back.

⚠ A refused gate writes nothing. The record is unchanged, and the act can be re-run once the refusal's cause is gone.

The engine refused the row

Class: gate-integrity.

What it means. The decision you posted did not satisfy the conditions the gate enforces. The refusal is not a single sentence — it is a numbered list of everything that is wrong, so you can fix them in one pass instead of re-running to discover the next one.

What to do. Fix what the list names. The refusal also prints the next act the record projects, so you do not have to work out what comes next from first principles. When you meet this in the browser rather than the terminal, the page shows the same list and the same projected next act.

⚠ This is the engine's answer, not the surface's. Both surfaces run the same validation, so switching from the browser to the terminal will not change the outcome.

Nothing resolved a workspace

Class: no-workspace.

What it means. The act had to be recorded somewhere and nothing determined where. Nothing was written.

What to do. Re-run naming the workspace explicitly: --workspace <path>.

⚠ Discovery from the current directory is convenient and not reliable — if you are automating anything, name the workspace every time rather than depending on where the command happens to run.

Named, not yet explained

These classes are real, deliberate and named. This section does not yet carry their resolution. If you are holding one, the name below is what it indicates.

classwhat its name indicates
access-log-unwritableThe server's --access-log path cannot be opened for appending, so the server refuses to start. ⚠ Worth knowing on sight: this product refuses to run without the audit trail it was told to keep.
capture-invalidA capture was supplied and is not well formed.
config-init-incompleteConfiguration was started and not finished, so there is not enough of it to act on. ⚠ Related: unknown configuration keys are refused against an explicit accepted vocabulary listed in the error — there is no permissive fallback, and a misspelled setting never silently does nothing.
init-collisionInitialisation found something already present where it would create.
merge-preconditionsThe conditions a merge requires were not all met; the refusal lists them. ⚠ Worth knowing: the merge is a human act — your invocation is the decision, and the engine refuses rather than deciding for you. See Merging.
merged-tree-does-not-buildGit combined the branch and its trunk cleanly, and the repository's declared build failed on the merged tree. The trunk was not moved; the refusal names the first failure and the next act.
gate-is-staleA stop-2 or review approval was asked for a commit the branch has already moved past. Nothing was written; look at the current tip and decide again.
structural-bounceA document was returned for its structure rather than its content.
teardown-archiveTearing down a piece of work stumbled on its archive step. ⚠ The archive is written before anything is removed, so a refusal here is the safe order working.
teardown-provisioned-unresolvableTeardown could not resolve something that had been provisioned into the work area.
teardown-worktree-unknownTeardown was asked about a work area it does not know.
unknown-captureA capture was named that the record does not hold.
unknown-streamA stream was named that the record does not hold. ⚠ Check the spelling against what the record lists before concluding it is missing.
unknown-workspaceA workspace was named that is not known — as distinct from no-workspace, where none was named at all.
bridge-commit-refusedA commit to the workspace's governance repository broke one or more of its rules; every rule broken is listed. Nothing was staged or committed.
memory-carry-refusedCarrying memory entries into the governance repository was refused; the plan is reported and nothing was written.

Removing a worktree at teardown

saphan teardown <stream> --verify-archive removes the worktree only when every guard agrees. Each of these names the guard that declined; in every one, unless the name says otherwise, nothing was removed.

classwhat its name indicates
closure-removal-refusedA guard declined and nothing moved — not a failed step.
closure-removal-incompleteThe removal ran, and re-measuring afterwards did not find the place gone. The verdict is that measurement, never a step's exit code.
closure-place-unmeasuredThe place could not be measured, or the teardown gate's census does not name it. An unmeasured place is never treated as absent.
closure-transport-unreachableThe machine holding the place never answered. Reach the host, then re-run.
closure-place-not-a-worktreeGit does not resolve the path as the root of a working tree of its own.
closure-place-is-a-main-repositoryThe path is a main repository, not a linked worktree. ⛔ This is the case removal must never touch, and there is no override.
closure-place-not-ownedThe ownership claim over the place now differs from the one the teardown gate measured. A change of ownership blocks removal.
closure-evidence-not-persistedEvidence collected from the place has not been written anywhere that survives the removal.
closure-collect-unreadableThe place's contents could not be walked, so nothing could be said about them.
closure-collect-incompleteThe source's own inventory and the set of files delivered home disagree.
closure-persist-unverifiedA file written into the archive did not re-read to its recorded digest.
closure-persist-uncontainedA file name was not a single path element, so writing it would have left the archive directory.

Merging a pull request on a forge

These come from the console's pull-request merge — see Pull requests and forge integrations.

classwhat its name indicates
forge-not-configuredNo forge connection is available to the act. Configure one first.
pr-unknownThe record holds no pull request with that number, or no stream claims it.
pr-merge-preconditionsThe checks before the merge refused; the individual refusals travel with it, verbatim.
pr-stale-headThe head the person approved is not the head the forge now reports. Look again and decide again.
pr-merge-in-flightA merge of this pull request is already under way, or a previous attempt left something outbound and its outcome is unresolved. ⚠ The answer is "unknown, ask again" — never "nothing happened".
pr-merge-claimed-by-another-actorAnother person's act already claimed this merge.
pr-merge-act-failedThe act failed part-way. ⚠ Read the outcome that comes with it: it says whether anything had already left the machine.

On this page