Skip to content

Troubleshooting

What each failure means, what to check, and the safe next step.

Start with the exit code

Every command exits with one of six codes, and the code narrows the problem before you read anything else.

0   success
1   validation error      the file is well-formed but breaks a rule
2   structure invalid     the workspace does not match the specification
3   drift detected        the specification changed since .orv.lock
4   file error            missing, empty or unparseable file
5   internal error        a defect in the engine

One case does not come from the engine at all. A command invoked without a required argument — orvienm verify, orvienm new orvienm init with nothing after it — is rejected by the argument parser, which prints usage: and the missing argument by name, then exits 2 as command-line tools conventionally do. It is a usage error, not a statement about a workspace: read the first line of the output to tell the two apart.

Two commands report by default rather than failing: policy doctor both exit 0 while printing what they found. Pass --strict to either one to turn the same finding into exit 2. Detection is identical in both modes — only the exit code changes — so a step you add to a pipeline cannot start failing it until you ask.

Reading the file

File not found: structure.yaml

exit: 4

Meaning
The path given to the command does not exist. Nothing was read and nothing was changed.
What to check
The engine's default filename is .orvienm.yaml, not structure.yaml or example.yaml. Confirm the file name and that you are in the directory you think you are.
Next step
Pass the correct path, or omit the argument on plan, apply, graph and policy to let the engine find .orvienm.yaml, orvienm.yaml or orvienm.yml.

Error: Invalid YAML format: mapping values are not allowed here

exit: 4

Meaning
The file could not be parsed as YAML. This happens before any Orvienm rule is applied, so the message comes from the YAML parser and includes the line and column.
What to check
Indentation, a missing colon, an unclosed bracket or a tab character where spaces are expected.
Next step
Fix the syntax at the reported line, then run validate again.

Error: YAML file is empty. / Root YAML structure must be a dictionary.

exit: 4

Meaning
The file parsed, but its top level is not a mapping — it is empty, or it is a list or a bare scalar.
What to check
That the file starts with keys such as version: and structure:.
Next step
Start from the minimal file in the Specification Reference.

Validation errors

Validation collects every problem and reports them together, one per line, under a Validation failed: header. Messages name the field and the fault; they do not carry line numbers, so locate the field by name.

Unknown field at root level: 'relationships'.

exit: 1

Meaning
The root key set is closed. Only version, structure, style and policy are accepted, and anything else is rejected rather than ignored.
What to check
Keys carried over from older drafts or from another tool. relationships, requires, profiles and appendix are all rejected.
Next step
Remove the key. If you need what it expressed, it is not implemented in this Alpha.

Missing required field 'version'. / Missing required field 'structure'. / Missing required field 'structure.name'.

exit: 1

Meaning
A required key is absent.
What to check
version and structure at the root; name and directories inside structure.
Next step
Add the missing key. Validation reports every problem at once, so one run tells you all of them.

'structure.directories' must be a list. / 'structure.directories' cannot be empty.

exit: 1

Meaning
directories is present but is not a non-empty YAML list. A common cause is writing it as a nested mapping.
What to check
That each directory is a list item under directories:, not an indented key.
Next step
Convert nested mappings to a flat list. Nested mapping syntax is not supported.

Directory '/data' cannot be an absolute path.

exit: 1

Meaning
Entries must be relative. A specification is not allowed to reach outside the workspace.
What to check
Leading slashes, and Windows drive letters such as C:\data.
Next step
Express the path relative to structure.name.

Directory '../up' cannot contain path traversal ('..').

exit: 1

Meaning
Traversal is rejected, for the same containment reason.
What to check
Any .. segment anywhere in the entry.
Next step
If the directory genuinely belongs elsewhere, it belongs to a different specification.

Duplicate directory paths are not allowed.

exit: 1

Meaning
Two entries normalise to the same path. They do not have to look identical — a and ./a collide, as do docs and docs/.
What to check
Entries that differ only by a ./ prefix, a trailing slash or separator style.
Next step
Remove one of them.

Directory name 'a:b' contains invalid character ':'.

exit: 1

Meaning
The characters < > : " \ | ? * are rejected in directory entries. Forward slashes are allowed.
What to check
Colons in particular, which YAML also treats specially.
Next step
Rename the directory.

Planning, applying and verifying

Drift detected — Current YAML fingerprint differs from .orv.lock.

exit: 3

Meaning
Apply is drift-gated. The specification has changed since the lock file was written, so apply refuses to run. Nothing was modified.
What to check
Whether the change to the specification is intended. Note that drift here means the file changed, not the filesystem — editing version, style, structure.name or the directory list all change the fingerprint.
Next step
If the change is intended, delete .orv.lock and apply again; apply creates whatever the change added, keeps everything already there, and a new lock is written. Removing the lock accepts every edit in the file at once, so read the specification first. To preview without touching the gate, use apply --dry-run.

Plan prints '? undeclared build/' and a non-zero Undeclared count.

exit: 0

Meaning
Plan found a directory the specification does not declare. It is reporting, not scheduling: apply contains no deletion path and will not remove it.
What to check
Whether the directory should be declared. Build output, virtual environments and scratch directories commonly appear here.
Next step
Add it to directories if it belongs to the structure, or leave it — it is safe either way. Nothing removes it.

A directory added to the specification was not created by apply.

exit: 3

Meaning
Apply grows an existing structure, so a newly declared directory is created normally. What stops it is the drift gate: editing the specification changed its fingerprint, so apply exited 3 without touching anything. Plan still reports '+ create' for the entry because plan is read-only and is not gated.
What to check
Whether apply printed 'Drift detected' and exited 3 rather than reporting the structure as compliant.
Next step
If the change is intended, delete .orv.lock and apply again. Apply then creates the new directory, keeps everything already there, and writes a new lock. Earlier Alpha builds could not do this at all — apply exited 2 with 'Existing structure is INVALID' even after the lock was removed.

Apply exits 2 with 'Error while creating structure'.

exit: 2

Meaning
A file already occupies a path the specification declares as a directory — either a declared entry or an intermediate a nested entry implies. Apply checks for this before it touches disk, so nothing at all was created: no partial tree is left behind.
What to check
The paths listed under 'A file already occupies a path the specification declares as a directory'. Each one is a file standing where a directory is declared.
Next step
Rename or move the file, then apply again. Apply never opens, overwrites or removes it — your file is left byte for byte as it was.

Doctor reports CRITICAL with orphan directories after a successful apply.

exit: 0 · 2 with --strict

Meaning
The workspace contains directories the specification does not declare. Intermediate directories created for a nested entry are not counted here — they are part of the declared structure.
What to check
The orphan_directories list under doctor --json. Build output and scratch directories are the usual cause.
Next step
Declare them if they belong to the structure, or accept the report: nothing removes them.

Verify prints Status: INVALID and exits 2.

exit: 2

Meaning
A declared directory — or one implied by a nested entry — is missing from the workspace. A regular file standing at a declared path counts as missing too: a declared directory is satisfied only by a directory. Verify is a read-only check and changed nothing.
What to check
The list of missing directories printed beneath the status line.
Next step
Apply the structure, or correct the specification if the directory should not be declared. Verify's exit code can be used directly as a pipeline gate.

Status reports Lock file: NOT FOUND after applying.

exit: 2

Meaning
A successful apply records the lock whether it created the structure, grew it, or found it already compliant. NOT FOUND after applying therefore means the apply never reached that point.
What to check
Whether the run was a --dry-run, or whether apply was blocked by the drift gate or failed. None of those write a lock.
Next step
Run apply without --dry-run and confirm it exits 0; the lock is written on the same run.

Policy reports a violation but the command still succeeds.

exit: 0

Meaning
The policy command reports by default: it prints the violation and exits 0, so adding a policy block cannot fail a pipeline that was green the day before. --strict is the opt-in that turns the same finding into exit 2.
What to check
The printed violation list, which gives each path relative to the structure root.
Next step
Accept the report, or pass --strict to gate on it. doctor --strict, status and verify also exit 2 on a structural problem.

UnicodeEncodeError: 'charmap' codec can't encode character

exit: 5

Meaning
A Windows console using a legacy code page cannot render the status glyphs the CLI prints.
What to check
Whether the terminal is running in an encoding other than UTF-8.
Next step
Set PYTHONIOENCODING=utf-8 in the environment, or run the command in a UTF-8 terminal.

If none of these match

Confirm the specification first with orvienm validate .orvienm.yaml, then inspect the workspace with orvienm doctor .orvienm.yaml --json, which reports the root, missing directories, undeclared directories, lock presence and fingerprint state in one object.

The Specification Reference lists every accepted key and rule, and the CLI Reference gives each command's exact behaviour and exit codes.