compositeerrors

package
v0.19.1064 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: AGPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package compositeerrors defines the typed, embedded error abstraction used across the Nuon platform.

A CompositeError is a regular Go error (it satisfies the standard error interface) plus typed metadata: a discriminator, a severity, and an optional list of structured Sections. That metadata lets the dashboard present a rich, opinionated view without losing the ability to be returned through the call stack like any other error.

Composite errors are persisted by attaching a CompositeErrorData JSONB column to owner rows (component builds, sandbox runs, deploys, action runs, ..)

New typed errors are added by writing a struct that implements CompositeError in its own subpackage (e.g. compositeerrors/terraform/, compositeerrors/validation/).

Index

Constants

View Source
const (
	// HintSkipAutoRetry ("true"): the orchestrator should not auto-retry this
	// failure; park the step for manual retry instead. Used for errors that
	// won't resolve by retrying (e.g. a missing IAM permission).
	HintSkipAutoRetry = "skip_auto_retry"

	// HintRequeueAfter (integer seconds, e.g. "300"): the orchestrator should
	// back off for the given duration before retrying rather than parking.
	// Used for transient, time-bounded failures (e.g. quota/throttle).
	HintRequeueAfter = "requeue_after"

	// HintTerminal ("true"): the failure is not retryable at all (auto or
	// manual).
	HintTerminal = "terminal"

	// HintDocsURL: a documentation link the UI may surface as "learn more".
	HintDocsURL = "docs_url"
)
View Source
const SchemaVersion = 1

SchemaVersion is the current version of the frozen CompositeErrorData payload. It is stamped onto every record by New() so renderers and future migrations can reason about payloads written by older code.

Variables

This section is empty.

Functions

This section is empty.

Types

type CompositeError

type CompositeError interface {
	error // headline, the one-line message users see

	Type() Type
	Severity() Severity

	// Sections returns optional structured detail (what / why / fix).
	// Returning nil is fine; the headline alone is a valid view.
	Sections() []Section
}

CompositeError is a typed, structured error. Implementations satisfy the standard error interface (Error() returns the headline message), plus metadata used to persist and present the error in the dashboard.

type CompositeErrorData

type CompositeErrorData struct {
	// Version is the payload schema version (SchemaVersion at write time).
	Version int `json:"version"`

	Type     Type      `json:"type"`
	Severity Severity  `json:"severity"`
	Message  string    `json:"message"`
	Sections []Section `json:"sections,omitempty"`

	// Data is the typed, per-error-type payload: WHAT the error is. Closed
	// schema per Type. Read to render sections and by any future view.
	Data json.RawMessage `json:"data" swaggertype:"object"`

	// SourceID / SourceType identify the row this error originated on
	// (polymorphic, same shape as OwnerID/OwnerType). Set at the record site,
	// e.g. ("runner_job_execution_results", "<result id>"). Enables a future
	// JOINable view without a separate error table.
	SourceID   string `json:"source_id,omitempty"`
	SourceType string `json:"source_type,omitempty"`

	// Hints is the open annotation/directive bag: HOW to handle or present the
	// error. Canonical keys (Hint*) are honored by specific consumers.
	Hints Hints `json:"hints,omitempty"`
}

CompositeErrorData is the JSONB GORM column attached to owner rows. It captures a typed CompositeError's payload along with its headline message and structured sections, all frozen at write time.

To use, add this to a GORM model struct:

CompositeError *compositeerrors.CompositeErrorData `json:"composite_error,omitempty" gorm:"type:jsonb"`

func New

func New(e CompositeError, opts ...Option) (*CompositeErrorData, error)

New constructs a CompositeErrorData from a typed CompositeError. The implementation's data, headline message, sections, and (optionally) hints are captured at this point and frozen on the resulting record. Sections and Hints are copied so a shared source (e.g. a package-level default hints bag) cannot be mutated through the persisted record. Options apply record-site context such as provenance.

It returns an error when the typed payload cannot be marshalled, so a serialization failure surfaces at the call site instead of silently persisting a record with a null payload.

func (CompositeErrorData) GormDataType

func (CompositeErrorData) GormDataType() string

GormDataType tells GORM to use a jsonb column.

func (*CompositeErrorData) Scan

func (c *CompositeErrorData) Scan(value any) error

Scan implements database/sql.Scanner.

func (*CompositeErrorData) Value

func (c *CompositeErrorData) Value() (driver.Value, error)

Value implements driver.Valuer.

type Hints added in v0.19.1024

type Hints map[string]string

Hints is an open annotation bag carried on a CompositeError. Unlike Data (which is the typed, per-error-type description of WHAT the error is), Hints describes HOW the platform should handle or present the error. It is cross-cutting and not tied to any single error type's schema.

Values are always strings to keep a single, unambiguous wire format inside the JSONB payload (a map[string]any would round-trip numbers as float64 and drift). Consumers read canonical keys through the typed accessors below, which own the coercion. Non-scalar values belong in Data, not Hints.

The bag is open, but the keys a consumer ACTS ON are a documented, closed set (the Hint* constants). An error may attach arbitrary annotation keys, but only canonical keys carry behavior.

func NewHints added in v0.19.1055

func NewHints() Hints

NewHints returns an empty bag ready for the With* setters. Prefer the typed setters over raw map literals so canonical keys and value formats stay correct (a misspelled key or malformed value silently becomes a no-op).

func (Hints) Clone added in v0.19.1055

func (h Hints) Clone() Hints

Clone returns a shallow copy of the bag, or nil when empty. Use it before mutating a Hints value that may be shared (e.g. a package-level default).

func (Hints) DocsURL added in v0.19.1024

func (h Hints) DocsURL() string

DocsURL returns the documentation link, or "" when unset.

func (Hints) RequeueAfter added in v0.19.1024

func (h Hints) RequeueAfter() (time.Duration, bool)

RequeueAfter returns the back-off duration and whether it was set. A missing or malformed value returns (0, false).

func (Hints) SkipAutoRetry added in v0.19.1024

func (h Hints) SkipAutoRetry() bool

SkipAutoRetry reports whether the orchestrator should skip auto-retries.

func (Hints) Terminal added in v0.19.1024

func (h Hints) Terminal() bool

Terminal reports whether the failure is not retryable at all.

func (Hints) WithDocsURL added in v0.19.1055

func (h Hints) WithDocsURL(url string) Hints

WithDocsURL attaches a documentation link the UI may surface as "learn more".

func (Hints) WithRequeueAfter added in v0.19.1055

func (h Hints) WithRequeueAfter(d time.Duration) Hints

WithRequeueAfter sets the back-off before retrying. A negative duration is ignored so the bag never carries a malformed value.

func (Hints) WithSkipAutoRetry added in v0.19.1055

func (h Hints) WithSkipAutoRetry() Hints

WithSkipAutoRetry marks the failure so the orchestrator parks the step for manual retry instead of auto-retrying.

func (Hints) WithTerminal added in v0.19.1055

func (h Hints) WithTerminal() Hints

WithTerminal marks the failure as not retryable at all.

type HintsProvider added in v0.19.1024

type HintsProvider interface {
	Hints() Hints
}

HintsProvider is an optional capability implemented by typed CompositeError values that want to attach hints. New() captures Hints() at write time, the same way it captures Sections().

type Option added in v0.19.1024

type Option func(*CompositeErrorData)

Option customizes a CompositeErrorData at construction. Options apply record-site context (e.g. provenance) that the typed error doesn't know.

func WithSource added in v0.19.1024

func WithSource(sourceType, sourceID string) Option

WithSource records where the error originated. sourceType is the row kind (polymorphic table name, e.g. "runner_job_execution_results"); sourceID is that row's id.

type Section

type Section struct {
	Heading string      `json:"heading"`
	Body    string      `json:"body"`
	Kind    SectionKind `json:"kind,omitempty"`
}

Section is a heading + body attached to a CompositeError. Kind controls how the body is rendered and whether it is treated as trusted (see SectionKind).

func CodeSection added in v0.19.1055

func CodeSection(heading, body string) Section

CodeSection builds an escaped monospace code section. Safe for untrusted raw output; do not wrap the body in markdown fences.

func MarkdownSection added in v0.19.1055

func MarkdownSection(heading, body string) Section

MarkdownSection builds a trusted, markdown-rendered section. Only pass hand-authored, code-controlled content, never raw tool output.

func TextSection added in v0.19.1055

func TextSection(heading, body string) Section

TextSection builds an escaped plain-text section. Safe for untrusted values.

type SectionKind added in v0.19.1055

type SectionKind string

SectionKind tells the renderer how to interpret a Section body, and, for security, whether the body is trusted. Untrusted content (raw tool output, values extracted from an error) must never be rendered as markdown: the dashboard's markdown pipeline enables raw HTML and runs custom-component extraction over the string, so a crafted payload could escape a code fence and inject content. Use SectionText/SectionCode for anything derived from tool output, and reserve SectionMarkdown for hand-authored, trusted prose.

const (
	// SectionMarkdown renders the body as markdown. Only for trusted, code-
	// authored content. It is also the assumed kind for legacy records that
	// predate this field.
	SectionMarkdown SectionKind = "markdown"
	// SectionText renders the body as escaped plain text, preserving
	// whitespace. Safe for untrusted single- or multi-line values.
	SectionText SectionKind = "text"
	// SectionCode renders the body as an escaped monospace code block. Safe for
	// untrusted raw output (terraform/helm logs, an AWS response, ...).
	SectionCode SectionKind = "code"
)

type Severity

type Severity string

Severity controls how the dashboard presents an error.

const (
	SeverityFatal   Severity = "fatal"
	SeverityError   Severity = "error"
	SeverityWarning Severity = "warning"
	SeverityInfo    Severity = "info"
)

type Type

type Type string

Type is the discriminator string for a CompositeError implementation (e.g. "terraform.error", "validation").

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL