Documentation
¶
Overview ¶
Package errors provides structured, actionable error reporting for the pasture system.
Every error carries a Category (connection, workflow, validation, config, storage), a short plain-language What field, a Why/Where/Impact/Fix tuple describing the cause/location/consequence/recovery, and implements the standard error interface so it can be used anywhere Go errors are expected. Use errors.As() to extract the full StructuredError from any wrapped error chain.
User-facing output (Report and the Stringer) follows a plain-language convention: a top "Error:" line summarising the category in one short sentence (Category-derived header), then a vertically aligned block with full English labels (Problem / Reason / Where / Impact / How to fix). Body text must avoid project-internal jargon — translate code-level terms into ordinary English. The "How to fix" section is numbered when there are multiple alternatives, with concrete shell commands on indented lines.
Top-line headers per Category (see categoryHeader):
CategoryConnection → "Error: Couldn't connect." CategoryWorkflow → "Error: A workflow step failed." CategoryValidation → "Error: The input wasn't valid." CategoryConfig → "Error: There's a problem with the configuration." CategoryStorage → "Error: A storage operation failed." (unrecognised) → "Error: Something went wrong."
The Problem: line then carries the SPECIFIC What value, so the headline and Problem elaborate rather than duplicate.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Category ¶
type Category string
Category classifies the error domain and drives exit-code selection.
The category is intentionally NOT shown verbatim in the user-visible "Error:" line — it remains available programmatically (via the Category field and via ExitCode) for log lines, exit-code mapping, and forensic inspection. The user-visible header is derived from the category via categoryHeader so the top line is plain English, not the raw enum string.
const ( // CategoryConnection indicates the daemon could not reach Temporal. CategoryConnection Category = "connection error" // CategoryWorkflow indicates a Temporal workflow or activity failure. CategoryWorkflow Category = "workflow error" // CategoryValidation indicates bad user input or missing required fields. CategoryValidation Category = "validation error" // CategoryConfig indicates a configuration file or environment variable problem. CategoryConfig Category = "config error" // CategoryStorage indicates a persistence-layer failure: SQLite open // errors, schema migration failures, or schema-version mismatches between // the binary and the on-disk database. See PROPOSAL-2 §7.10.5 for rationale. CategoryStorage Category = "storage error" )
type StructuredError ¶
type StructuredError struct {
// Category classifies the error domain (connection, workflow,
// validation, config, storage). Drives exit-code selection and the
// top-line header (via categoryHeader). The raw enum string is NOT
// surfaced in user-visible output.
Category Category
// What is one short plain-English sentence summarising what went wrong
// SPECIFICALLY (the value the user passed, the file that failed, etc.).
// Surfaced as the Problem: line. Avoid type names, SQL columns,
// and protocol references.
What string
// Why explains the underlying cause in plain English. Translate
// technical roots ("ParseTaskId returned ErrInvalidFormat" → "the ID
// didn't have the required separator") so a non-specialist can act on
// it. Surfaced as the Reason: line.
Why string
// Where describes what the user (or system) was doing when the error
// occurred, with the code location parenthetically. Example:
// "Starting the epoch (handlers/epoch.go in handlers.EpochStart)"
// Optional — when empty the Where: line is suppressed in user-visible
// output. See package docs.
Where string
// Impact describes the consequence to the caller in plain English.
// "The workflow can't start," not "the workflow boundary cannot
// satisfy R5/D5 alignment."
Impact string
// Fix provides concrete recovery steps. When multiple alternatives
// exist, format as numbered items joined with "\n" — see FixStep
// helpers below for the canonical shape. Each step starts with a
// plain-English sentence followed by an indented shell command.
Fix string
// Cause optionally wraps the underlying error for log-debugging and for
// errors.Is / errors.As traversal. It is NOT surfaced in user-visible
// output (Report) — that prose must be plain English with no Go symbol
// names, package qualifiers, or SQL column references. Set Cause when a
// translated Why field would otherwise lose the underlying error
// information that operators need in logs.
Cause error
}
StructuredError implements the error interface with actionable diagnostic fields.
All narrative fields (What, Why, Where, Impact, Fix) should be filled in so the reader can understand both the cause and the recovery without reading source code. Where is optional — when empty the line is suppressed in user-visible output. See package docs for the plain-language conventions all callers must follow.
func (*StructuredError) Error ¶
func (e *StructuredError) Error() string
Error implements the error interface.
Returns "<category>: <what>" — suitable for log lines or wrapping with fmt.Errorf("%w"). User-facing output should use Report or the package's Print helpers (which emit the full plain-language block).
func (*StructuredError) Report ¶
func (e *StructuredError) Report(w io.Writer)
Report writes the full plain-language error block to w.
Output format (vertically aligned for visual parseability):
Error: <category-derived plain-language header>
Problem: <what — specific to this occurrence>
Reason: <why>
Where: <what was happening (file:line in code parenthetically)>
Impact: <impact>
How to fix:
<fix body — already includes numbered steps and indented commands>
The top "Error:" line is derived from Category via categoryHeader so it is a generic plain-English summary; the specific situation appears in the Problem: line. This avoids the headline-duplicates-Problem anti-pattern.
The Where: line is suppressed entirely when StructuredError.Where is empty — better than printing an empty label.
Multi-line What/Why/Where/Impact/Fix values are wrapped to align under the label column so the whole block stays scannable.
func (*StructuredError) Unwrap ¶
func (e *StructuredError) Unwrap() error
Unwrap returns the optional underlying cause so errors.Is / errors.As can traverse the chain without exposing the raw cause to user-visible output.