Messages¶
Every error, refusal, run outcome, validation check, status and limitation in OpenFlowsheet carries a code, and every code has an explanation written for a person who has just made the mistake. The explanation is rendered when you read it, from the message catalogue; the machine message beside it never changes, so a program that matched the old text still matches.
The pages of this section list every code, one section per code:
| Page | Codes |
|---|---|
| API errors | the error codes every transport returns (ApiError.code) |
| Refusals | the specific reasons a request, a revision, a solve or a project is refused |
| Run outcomes | how a solve ended (RunResult.outcome) |
| Validation checks | the checks of a validation report |
| Statuses | validation statuses and certificate words |
| Limitations | what this version does not do, one section per support-matrix row |
| Notices | messages that are not failures |
| Jobs | why a job ended the way it did |
Each explanation's docs link points at its code's section here.
Reading an explanation¶
Python's str() of an error, and the command line's stderr, show the explanation in layers: what
happened and where, why (with the numbers), what to do, then the kind, the code and the machine
details.
<summary>
Cause: <the inner reason, when the summary is the outer one>
Why: <the rule, with the numbers>
Do: <what to change>
Hint: <the binder's hint, verbatim>
Kind: <one of the five kinds below>
Code: <code>[, in <outer codes>] (openflowsheet explain <code>)
Docs: <this site's section for the code>
Details: <the machine message, unchanged>
A line is left out when it has nothing to say. For example, the example of
phase_regime_mismatch, a turbine outlet declared wet that
comes out vapour:
The solve stopped before its first iteration: unit 'T' could not compute its outlets from the starting values.
Cause: Stream 'S4' is not in its declared phase: it is declared wet (vapour + liquid), but at these conditions it is vapour.
Why: At 10000 Pa the enthalpy of 'S4' is 47330 J/mol, above the saturated-vapour value 46570 J/mol, so the stream is vapour, not wet (vapour + liquid).
Do: Declare 'S4' as vapour. If you expected wet (vapour + liquid), check the specifications that set the conditions upstream of 'S4'.
Kind: Input problem: something in the flowsheet or the request needs to change.
Code: phase_regime_mismatch, in INITIALIZATION_FAILED → initializer_failed (openflowsheet explain phase_regime_mismatch)
The five kinds¶
| Kind | Meaning |
|---|---|
input |
Input problem: something in the flowsheet or the request needs to change. |
not_supported |
Not supported in this version: a limitation of OpenFlowsheet, not an error in your flowsheet. The explanation names the limitation (gap). |
numerical |
Numerical failure: the solver did not find the solution; your flowsheet may be correct. |
bug |
Internal error in OpenFlowsheet: please report it. |
notice |
Notice: not a failure. |
Explanations as data¶
Programs and agents read the same explanation as a document
(application-results.schema.json#/$defs/explanation): code, family, kind, complete,
summary, cause, where, why, action, hint, elements (the flowsheet ids involved), numbers
(each with its label, SI value, unit and quantity kind), gap (for a not-supported code: the
limitation and the missing capability), chain (the codes, outer to inner) and docs.
- A refusal on any transport carries it as
detail.explanationof theApiErrordocument. - A solve that did not converge carries it as
RunResult.failure.explanation;failurealso holds the outcome, the stored failure message, the implicated elements, the suggested actions and the failure bundle's artifact id.
A section that says no plain-language explanation is written yet is a code whose entry is still the technical summary; the code, the kind and the machine message are complete.
Asking for a code: explain¶
explain returns a code's catalogue entry: its title, kind, the templates of its summary, why and
action (each parameter shown as <name>), the parameters, the gap, related codes, rendered examples
and its docs link. It reads no project.
- Command line, no project needed:
openflowsheet explain phase_regime_mismatchprints the entry as text,--jsonas the document. An unknown code exits 6 (not_found) and suggests close codes. - Python:
LocalApplication.explain(code)returns aMessageEntry. - HTTP:
GET /v1/explain/{code}. MCP: theexplaintool. - Every transport refuses an unknown code
not_found, withdetail.codeanddetail.suggestions(up to five codes within three edits, case-insensitive).
The beginner-mistake corpus¶
The explanations are tested against a corpus of beginner mistakes, tests/fixtures/msg/corpus.yaml,
each built from the README's Rankine change set through the public API. A case records:
idand themistake, in a sentence;- the emitted
code,kindandchain, exactly; - the
elementsids that must appear inexplanation.elementsand in the summary (line 1 and its cause), andin_summarytexts the summary must contain; - the
numbersnames, with values where an independent expectation exists; - an
action_tokenthe action must contain, and thegapof anot_supportedcode; - the complete rendered text per surface,
text, as an exact golden (regenerated only bypytest tests/test_msg_corpus.py --msg-updateand reviewed in the diff); - the
surfacesit runs on; a case on all four must give one document on all of them; pendingitems: what the design expects and the software does not emit yet, each a strict expected failure that turns the test red the day it holds.
A case's Python setup function lives in tests/test_msg_corpus.py, keyed by its id. A case records
the code the software actually emits; a code that is too unspecific is reported, never invented.