On this page
Failure catalogues: every way a functionality fails
A command that fails tells you what failed. Does it also tell you why, what it saw and what fixes it, and has anyone ever made it fail that way on purpose? A failure catalogue is the answer written down once, in code, beside the functionality that raises it: every way it can fail, including the ways nobody has met yet.
The unit is the functionality, not the command. One command runs several functionalities — enrolling a machine reads the registry, probes the machine over SSH and writes the registry back — and the same registry read runs under many commands. So each functionality declares its own causes once, names the entries that start it (commands, Stado Desktop screens) and the functionalities it uses, and a command meets every cause of what it starts and of everything that uses in turn.
What a cause declares
| field | what it says |
|---|---|
id |
the cause, lowercase words joined by -, stable within its functionality |
failed |
the step that failed, as you would name it |
cause |
why it failed |
observed |
the state the refusal shows: the values that do exist, the path read, what the layer below answered |
remedy |
what fixes it: the command to run, the declaration to change |
code, exit |
the failure code and the exit status the command leaves |
test |
the real test that provokes it, tests/<area>/<file>::<test name> |
A functionality declares its id (its failure point, stado.fleet.enroll), a
summary, its documentation page, its entries, the functionalities it
uses and the causes of its own steps. One made only of what it uses declares
no cause of its own; one only other functionalities run names no entry.
The same declaration produces the refusal you read (the Error: line, a
fix: line, and a cause: line), the cause, functionality and remedy
of the --json envelope, the stado errors show listing and the causes on
the command's page in the CLI reference. The cause: line names
the cause by the functionality that declares it, because an id alone names
no one cause (the store's missing and the vault's are two), and the
catalogue to read for the rest: the one the command starts when it has one,
otherwise the declaring functionality's own.
cause: stado.registry.read.registry-missing; `stado errors show stado.registry.read` lists every way it fails
A command page that starts no declared functionality says so first: `stado <command>` starts no functionality that declares how it fails yet, so the ways it fails at run time are not listed here; `stado errors list` names every such command, and the sentences below are read from its help text.
The layers every command reads through
Most commands meet the same few layers: the object store, the vault, this
machine's configuration and files, the fleet registry, the host channel, and
the layers a family of commands shares, such as how every stado service
verb finds what it acts on. Each declares its own causes once, raised by the
one conversion every command's failure passes through, whichever command met
it. The layers every command reads through lists each
layer with its causes.
Which functionalities declare one, and which commands start none
stado errors list [--json | --markdown]
list prints one line per functionality that declares a catalogue (its id,
how many causes of its own, its entries or run by the functionalities that use it, and its page), then reads the CLI's own command tree and says how many
of the commands that run something, a command with no subcommand of its own,
hidden ones included, a functionality names among its entries:
<named> of <commands> commands start a functionality that declares how it fails; <rest> start none:
stado <command>
…
With --json the answer is {"operations": [...], "commands": <n>, "undeclared": ["stado <command>", ...]}, each functionality carrying its
operation (the id), entries, uses, summary, docs and causes.
--markdown prints each catalogue's documentation section.
stado errors show <functionality> [--json | --markdown]
show prints the functionality, how it is started, what it uses, and every
cause it can meet — its own and those of every functionality it uses — each
with declared by <functionality>, what failed, why, what was observed, the
fix, its code, exit status and test. A functionality that declares no catalogue
is refused with the usage status (cause stado.errors.show.functionality-unknown):
showing the failure catalogue of '<id>': no functionality of this Stado declares a catalogue under that id; observed: the functionalities that do: <ids>, fix: name one of them as stado errors list prints it.
Check the catalogues against the CLI and the repository
stado errors check --source <directory>... --repository <checkout> [--baseline <file>] [--tests-baseline <file>] [--json]
check exits 0 only when nothing below is found, and otherwise refuses with
exit 1 (cause stado.errors.check.standard-not-met): holding the catalogues, the commands and the source to the error standard: <n> problem(s) stand; observed: <every finding, joined by "; ">:
- a declaration that is not one: a cause without its fix or test, an id that
is not lowercase words, a usage refusal declared retryable, the catch-all
unknown, an empty entry, a functionality that uses itself or declares no cause and uses nothing (eachcause <id>: …oroperation <id>: …); - what only the whole catalogue shows:
operation <id> is declared twice,operation <id>: it uses <id>, which the catalogue does not list; list every functionality the product runs, andoperation <id>: nothing starts it: it names no entry and no functionality of the catalogue uses it; - an entry naming a command the CLI does not have:
the functionality <id> names the entry, which this CLI does not have; name the command as a person types it; - a declared cause whose test the repository does not hold and the
--tests-baselinelist does not name:<functionality>.<cause> names the test <test>, which the repository does not hold: <why>; write that test, or name the one that provokes this cause, where<why>is<checkout>/<file> is absent,<checkout>/<file> cannot be read: <cause>,<checkout>/<file> does not parse as Rust: <parser's words>or<checkout>/<file> declares no #[test] fn <name>. A function counts when it carries a test attribute (#[test],#[tokio::test]) in the file or in a module written inline in it; - a test the
--tests-baselinelist (["tests/<area>/<file>::<name>", …]) names that is no longer absent, or that no cause names:the tests baseline allows <test> to be absent, but no declared cause names it as an absent test; remove it from the baseline. The list only shrinks: Stado keeps it instado-rs/errors-tests-baseline.json, and its quality gateerrors-tests-baselinerefuses every candidate that adds a cause without its test or writes a test without taking it off the list; - every command no functionality names:
stado <command> starts no functionality that declares how it fails; declare every functionality it runs as a wisent_errors::Operation naming it among its entries, each cause with the real test that provokes it, and list it inoperations()of stado-rs/src/cli/errors/mod.rs; - an error message in the source under each
--sourcedirectory holding a generic sentence ("did not succeed", "operation failed") beyond what--baseline({"<path>": {"<sentence>": <count>}}) allows, and a baseline entry above what the file still holds (lower it to <count>).
It first says what it read:
<n> functionality(ies) declare <c> cause(s), <m> of which name a test the repository does not hold; <u> of <commands> commands start no declared functionality; <g> generic sentence(s) in the source; <p> problem(s)
With --json the same counts are operations, causes, missing_tests,
commands, undeclared and generic_sentences, every absent test under
missing (each {cause, test}), the problems about tests under
test_problems, and every finding under problems, followed by the
refusal's envelope.
Refusals that end the check without a verdict, each a declared cause of
stado.errors.check with its fix: line (the repository is judged before
anything else is read):
repository-not-directory, usage status 2:reading the declared causes' tests from <path>: it is not a directory, so no test file can be read from it; observed: --repository <path>;- no
--repositoryor no--source: the parser names the missing option, usage status 2; source-unreadable, usage status 2:scanning the source directory <path> for generic sentences: the directory, or an entry of it, cannot be listed; observed: <the system's answer>;source-file-unreadable, exit 1:reading the source file <path> for generic sentences: the file cannot be read as UTF-8 text; observed: <the system's answer>;baseline-unreadable, usage status 2:reading the baseline <path>: the file cannot be read; observed: <the system's answer>;baseline-malformed, usage status 2:reading the baseline <path>: it is not {"<path>": {"<sentence>": <count>}}; observed: <the parser's answer>;tests-baseline-unreadable, usage status 2:reading the tests baseline <path>: the file cannot be read; observed: <the system's answer>;tests-baseline-malformed, usage status 2:reading the tests baseline <path>: it is not a JSON array of test names, each tests/<area>/<file>::<name>; observed: <the parser's answer>.
A product written in another language prints the same JSON from its own
errors list --json; node ci/error-standard.mjs catalogue <file> --repository <checkout> --entries <entries.json> in wisent-errors applies the
same rules to it, with the product's own list of entries.
In Stado Desktop
Releases → Available operations… carries List every functionality's
failure catalogue and the commands that start none, Read every declared
way one functionality fails and Check that every command starts
functionalities declaring how they fail, each cause with its real test. Each
runs the same stado errors command with --json on the selected Stado API
host and shows its answer or refusal.
The real journey
kompilator test --manifest-path stado-rs/Cargo.toml --test errors-catalogues
It runs the checkout's own stado in an isolated home. list must split
every command the binary runs into the ones a functionality names among its
entries and the ones starting none, each answering --help. check runs
against a fixture repository holding one cause's test as a #[test] function
in an inline module (not refused), one cause's function without a test
attribute and one file that does not parse (each refused with its sentence),
then against an empty repository (every cause's file absent), and must refuse
a --repository that is not a directory and a check that names none. Every
command, its exit status and both streams are kept with the source revision
under .build/errors-catalogues/.
kompilator test --manifest-path stado-rs/Cargo.toml --test errors-tests-baseline
The quality gate of the same name. It checks this checkout behind
stado-rs/errors-tests-baseline.json and must find no test problem; a list
naming one more test that exists must be refused naming exactly that test;
an unreadable list and a list that is not an array must each be refused with
its declared cause. Each run's command and answer are kept under
.build/journeys/errors/.
Source: this website