Documentation
¶
Overview ¶
Registry fragment: ACME certificate codes (E470-E474, P7-LIVE-22). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation. E473 and E474 stay unregistered until a producer exists. The commands raise these only in v1.5 mode (ADR 0021); v1.4 keeps E151.
Registry fragment: off-box backup status and restore drill codes (E217-E221, P7-PROD-07). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation. E221 is spare.
Registry fragment: zero-config backup key codes (E222-E224, P7-PROD-08). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: bundle install app-ready codes (E135-E136), owned by P7-PLUG-19. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: bundle remove codes (E133-E134), owned by P7-PLUG-20. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: canon engine codes (E410, P7-CANON-21). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation (E411-E412 are spare in this fragment).
Registry fragment: cli codes (E400-E449). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: config codes (E050-E099). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: config explain code (E434), owned by P7-SURF-06. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: custom-service (CS_N v2) codes E500-E502 and E528, owned by P7-ADOPT-01. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: database codes (E200-E249). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: deploy environment scoping code (E483, P7-DEPL-12). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: docker codes (E001-E049). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: domain codes (E350-E399). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: machine invocation gate and machine token codes (E424-E426, P7-SURF-25, EPIC SURF D14). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: health codes (E250-E299). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Purpose: register HTTP API transport refusals E428-E432 (SURF D14). Inputs: none. Outputs: error registry entries. Constraints: classes and exits are part of cli.http-api v1.
Registry fragment: init codes (E300-E349). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: machine invocation codes (E420-E423, P7-SURF-24). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation. E424-E426 belong to the gate fragment of P7-SURF-25.
Registry fragment: project lock codes (E455-E459, P7-LIVE-09). E456-E459 are reserved for this Ticket's owner Epic and stay unregistered until a producer exists. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: plugin-command mount codes (E405-E407, P7-CANON-01). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation (E408-E409 are spare in this fragment).
Registry fragment: nself.yaml validation codes (E435-E436), owned by P7-SURF-07. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: core object storage (E138 MinIO moved, E142 credentials), owned by P7-PLUG-60.
Registry fragment: project operation lock codes (E460-E464, P7-LIVE-13). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation. E461-E464 are reserved for this Ticket's owner Epic and stay unregistered until a producer exists.
Registry fragment: plugin Postgres-extension requirement codes (E507-E508, P7-ADOPT-06). Registered from init() through Register; see codes.go for the rules. The only producer is internal/plugin/requires.
Registry fragment: plugin codes (E100-E149). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: plugin command binary collision code (E141), owned by D-0259. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: plugin resolution and compose-fragment codes (E128-E131), owned by P7-PLUG-17. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: plugin manifest v2 codes (E111-E114), owned by P7-PLUG-01. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: plugin migration readiness codes (E118-E120), owned by P7-PLUG-59. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: plugin seed hook code (E127), owned by P7-PLUG-32. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: plugin install table tracking code (E140), owned by P7-PLUG-78. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: portable bundle codes (E515-E516, P7-ADOPT-23). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation. The reader in internal/portable is the only producer.
Registry fragment: change-plan codes (E450-E454, P7-LIVE-03). E454 is reserved for the reconcile Epic and stay unregistered until a producer exists. Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: ssl codes (E150-E199). Registered from init() through Register; see codes.go for the rules and codes_blocks.go for the allocation.
Registry fragment: vector-search codes (E513-E514, P7-ADOPT-07). Registered from init() through Register; see codes.go for the rules. The only producers are internal/database/vectorsearch and internal/database (TrackFunction).
Package errs is the sole home for structured, user-facing CLI errors and the process exit-code contract for the nSelf CLI.
Purpose: give every command a single place to (a) classify a failure by a stable code (E001-E449, see codes.go and the codes_<topic>.go fragments), (b) attach a What/Why/Fix explanation via CLIError (structured.go), and (c) map that failure onto one of the four canonical process exit codes (exit_codes.go, exit_error.go) so wrappers (CI runners, schedulers, ops scripts) can branch on outcome class without parsing stderr.
Inputs: sentinel errors declared in this file (errs.ErrDockerNotRunning etc.), or a Registry code passed to New/Newf/Wrap.
Outputs: *CLIError (implements error, formats as "[CODE] What / Why / Fix") and *ExitError (implements error + ExitCode() int for main() to read).
Constraints: named "errs" (not "errors") to avoid shadowing the Go standard library; other packages import as `nself-org/cli/internal/errs`. This package absorbed the sole responsibility for structured user-facing errors as of CLI-R14 (2026-08-23) — the parallel, unimported `internal/errors` catalog (ERR-INSTALL-*, ERR-LICENSE-*, etc. with a Message struct and its own HelpFooter) was deleted as a confirmed-dead duplicate: same shape (Code/What/Why/Fix), same category coverage (docker, config, plugin, license, ssl, database, health, init, domain), zero importers anywhere in the tree. Nothing from it was migrated because everything it did is already covered here via Registry + CLIError, and CLIError additionally carries the exit-code classification that the deleted package never had.
Package errs (exit codes) defines the canonical exit-code contract for the nSelf CLI. Every command path that can fail must map its failure to one of these codes so wrappers (CI runners, schedulers, ops scripts) can branch on outcome class without parsing stderr.
The codes are intentionally small and stable. Adding a new class requires a release-plan note. Re-using an existing class is preferred over inventing a new one.
Index ¶
- Constants
- Variables
- func Categories() []string
- func ClassFor(exitCode int) string
- func CodeForSentinel(err error) (string, bool)
- func Exit(code int) error
- func ExitCodeFor(err error) int
- func ExitWith(code int, err error) error
- func ExitWithf(code int, format string, args ...any) error
- func Register(entries ...CodeEntry)
- func RegistryErrors() []error
- type Block
- type CLIError
- type CodeEntry
- type Detail
- type ExitCoder
- type ExitError
- type Owner
- type Silencer
Constants ¶
const ( // ExitOK indicates successful completion. ExitOK = 0 // ExitUserError indicates the caller supplied invalid input: bad flag // value, missing required argument, malformed env, unknown subcommand. // The fix is on the user side. ExitUserError = 1 // ExitInfraError indicates a downstream infrastructure failure: docker // daemon down, port collision, network unreachable, disk full, plugin // runtime crash. Retrying after fixing the host condition may succeed. ExitInfraError = 2 // ExitAuthError indicates an authentication or authorization failure: // invalid license key, expired key, tier insufficient for the requested // plugin, missing OAuth credentials. ExitAuthError = 3 // ExitDestructiveBlocked indicates a destructive action was refused by // the safety guards: missing --force on prod, force_local mismatch, // confirmation prompt declined. ExitDestructiveBlocked = 4 )
Canonical exit codes. Must match the contract documented in .claude/docs/standards/exit-codes.md and surfaced via 'nself --help' in the EXIT CODES section.
Variables ¶
var ( // Docker ErrDockerNotRunning = errors.New("docker daemon is not running") ErrDockerNotInstalled = errors.New("docker not found in PATH") ErrComposeNotFound = errors.New("docker-compose.yml not found — run 'nself build' first") ErrPortConflict = errors.New("port already in use") // Config ErrWeakPassword = errors.New("password does not meet minimum length") ErrInsecurePassword = errors.New("password matches insecure pattern") ErrInvalidProjectName = errors.New("invalid project name format") ErrInvalidCORS = errors.New("CORS wildcards not allowed in production") ErrPlaceholderSecret = errors.New("secret is empty or matches a known placeholder value") // Health ErrServiceUnhealthy = errors.New("service health check failed") ErrHealthTimeout = errors.New("health check timed out") ErrServiceNotFound = errors.New("service not found") // Plugin ErrInvalidLicenseKey = errors.New("invalid license key format") ErrLicenseTierTooLow = errors.New("license tier does not include this plugin") ErrLicenseExpired = errors.New("license key is expired") ErrPluginNotFound = errors.New("plugin not found in registry") ErrPluginManifest = errors.New("invalid plugin manifest") ErrCircularDependency = errors.New("circular plugin dependency detected") ErrPluginUnsigned = errors.New("stable plugin is missing required signature — install refused") ErrPluginMissingChecksum = errors.New("stable plugin is missing required checksum — install refused") ErrDuplicatePluginSlug = errors.New("plugin slug is served by more than one unrelated registry entry") ErrTierNotEntitled = errors.New("license does not entitle this Licensed plugin") // SSL ErrMkcertNotFound = errors.New("mkcert not installed — falling back to OpenSSL") ErrSSLGenerationFailed = errors.New("SSL certificate generation failed") // Nginx ErrDuplicateRoute = errors.New("duplicate nginx route detected") // Domain / Port ErrInvalidDomain = errors.New("invalid domain name") ErrInvalidPort = errors.New("invalid port number") // Database ErrDatabaseNotRunning = errors.New("database is not running") ErrMigrationFailed = errors.New("database migration failed") ErrMigrationValidationFailed = errors.New("migration dry-run validation failed") ErrMigrationPrerequisiteMissing = errors.New("migration prerequisite object missing from live schema") ErrBackupFailed = errors.New("database backup failed") ErrBackupNotFound = errors.New("backup not found") ErrBackupVerifyFailed = errors.New("backup verification failed") ErrBackupRestoreFailed = errors.New("backup restore failed") ErrBackupEncryptFailed = errors.New("backup encryption failed") ErrBackupDecryptFailed = errors.New("backup decryption failed") ErrBackupRemoteFailed = errors.New("remote backup operation failed") ErrBackupPruneFailed = errors.New("backup pruning failed") ErrWALArchiveFailed = errors.New("WAL archive failed") // Disaster Recovery ErrDRDrillFailed = errors.New("DR drill failed") ErrDRPromoteFailed = errors.New("standby promotion failed") ErrDRRollbackFailed = errors.New("DR rollback failed") ErrDRFenceFailed = errors.New("split-brain fence failed") )
var Blocks = []Block{
{1, 49, "docker"},
{50, 99, "config"},
{100, 149, "plugin"},
{150, 199, "ssl"},
{200, 249, "database"},
{250, 299, "health"},
{300, 349, "init"},
{350, 399, "domain"},
{400, 449, "cli"},
{450, 479, "reconcile"},
{480, 499, "deploy"},
{500, 529, "adopt"},
{540, 549, "secret"},
}
Blocks is the ordered block table.
var ErrDestructiveBlocked = sentinel("destructive action blocked by safety gate")
ErrDestructiveBlocked is the package-level sentinel that command glue can wrap with fmt.Errorf("...: %w", errs.ErrDestructiveBlocked) so that ExitCodeFor classifies the failure as exit code 4 without an import cycle through internal/confirm.
var Owners = []Owner{
{1, 5, "existing", "codes_docker.go"},
{50, 56, "existing", "codes_config.go"}, {57, 59, "P7-REG-01", "codes_config.go"},
{60, 61, "P7-TRUTH-12", "codes_compat.go"},
{100, 105, "existing", "codes_plugin.go"}, {106, 110, "P7-REG-01", "codes_plugin.go"},
{111, 114, "P7-PLUG-01", "codes_plugin_manifest.go"},
{115, 117, "P7-PLUG-09", "codes_catalog.go"},
{118, 120, "P7-PLUG-59", "codes_plugin_migrate.go"},
{121, 124, "P7-PLUG-23", "codes_plugin_signature.go"},
{125, 126, "P7-PLUG-24", "codes_entitlement.go"},
{127, 127, "P7-PLUG-32", "codes_plugin_seed.go"},
{128, 131, "P7-PLUG-17", "codes_plugin_fragment.go"},
{132, 132, "P7-PLUG-64", "codes_entitlement_refresh.go"},
{133, 134, "P7-PLUG-20", "codes_bundle_remove.go"},
{135, 136, "P7-PLUG-19", "codes_bundle_install.go"},
{137, 137, "P7-PLUG-25", "codes_template.go"},
{138, 138, "P7-PLUG-60", "codes_object_storage.go"},
{139, 139, "P7-PLUG-31", "codes_update_stack.go"},
{140, 140, "P7-PLUG-78", "codes_plugin_track.go"},
{141, 141, "D-0259", "codes_plugin_cli_collision.go"},
{142, 142, "P7-PLUG-60", "codes_object_storage.go"},
{150, 151, "existing", "codes_ssl.go"},
{200, 202, "existing", "codes_database.go"}, {203, 216, "P7-REG-01", "codes_database.go"},
{217, 221, "P7-PROD-07", "codes_backup.go"}, {222, 224, "P7-PROD-08", "codes_backup_key.go"},
{250, 252, "existing+P7-REG-01", "codes_health.go"},
{300, 301, "existing", "codes_init.go"}, {350, 351, "existing", "codes_domain.go"},
{400, 404, "P7-REG-01", "codes_cli.go"},
{405, 407, "P7-CANON-01", "codes_mount.go"}, {410, 410, "P7-CANON-21", "codes_canon.go"},
{420, 423, "P7-SURF-24", "codes_invoke.go"}, {424, 426, "P7-SURF-25", "codes_gate.go"},
{428, 432, "P7-SURF-02", "codes_httpapi.go"}, {433, 433, "P7-SURF-03", "codes_mcpgen.go"},
{434, 434, "P7-SURF-06", "codes_config_explain.go"}, {435, 436, "P7-SURF-07", "codes_nself_yaml.go"},
{437, 437, "P7-SURF-30", "codes_registry_surface.go"},
{450, 454, "P7-LIVE-03", "codes_reconcile.go"}, {455, 459, "P7-LIVE-09", "codes_lock.go"},
{460, 464, "P7-LIVE-13", "codes_oplock.go"}, {465, 469, "P7-LIVE-18", "codes_images.go"},
{470, 474, "P7-LIVE-22", "codes_acme.go"},
{480, 482, "P7-DEPL-01", "codes_proxy.go"}, {483, 483, "P7-DEPL-12", "codes_deploy_env.go"},
{484, 487, "P7-DEPL-13", "codes_deploy.go"}, {488, 490, "P7-DEPL-15", "codes_promote.go"},
{491, 491, "P7-DEPL-18", "codes_archguard.go"}, {492, 499, "P7-DEPL-19", "codes_release_verify.go"},
{500, 502, "P7-ADOPT-01", "codes_custom_service.go"}, {503, 505, "P7-ADOPT-03", "codes_shared_proxy.go"},
{506, 506, "P7-ADOPT-21", "codes_shared_proxy_runtime.go"}, {507, 508, "P7-ADOPT-06", "codes_pg_requires.go"},
{509, 512, "P7-ADOPT-22", "codes_pg_image.go"}, {513, 514, "P7-ADOPT-07", "codes_vector_search.go"},
{515, 516, "P7-ADOPT-23", "codes_portable.go"}, {517, 524, "P7-ADOPT-10", "codes_importer.go"},
{525, 527, "P7-ADOPT-17", "codes_export.go"}, {528, 528, "P7-ADOPT-01", "codes_custom_service.go"},
{529, 529, "P7-ADOPT-10", "codes_importer.go"},
{540, 544, "P7-TRUST-03", "codes_secret_resolve.go"},
}
Owners lists the per-Ticket sub-ranges fixed by each owner Epic (D13), with the fragment each registers from. Spare and free numbers are deliberately absent: registering one is a RegistryErrors() problem. Sorted by Lo.
var Registry = map[string]CodeEntry{}
Registry maps error codes (E001..E999) to their metadata. It is filled by Register calls from the codes_<topic>.go fragment files during package init; treat it as read-only afterwards. New codes are added in a new fragment file inside the owning Epic's range (see codes_blocks.go), never by editing this map.
Functions ¶
func Categories ¶ added in v1.0.6
func Categories() []string
Categories returns all unique category names from the registry. The result is sorted so callers see a stable order.
func ClassFor ¶ added in v1.4.13
ClassFor names the exit class of a process exit status: user (1), infra (2), auth (3), destructive_blocked (4), and other for anything else.
func CodeForSentinel ¶ added in v1.4.13
CodeForSentinel returns the registry code of the sentinel that err matches through errors.Is, and whether there was a match.
Purpose: the single place that turns a wrapped sentinel into an error code, used by ExitCodeFor and Describe so both always agree.
Inputs: any error, possibly wrapped with %w or joined.
Outputs: (code, true) on a match; ("", false) for nil or an unmapped error. When several sentinels match (errors.Join), the one with the highest exit class wins (auth > destructive_blocked > infra > user, see classRank); ties go to the first row in table order.
func Exit ¶ added in v1.3.0
Exit returns an error that exits with code and prints nothing. Use it when the command has already written its own diagnostics to stderr.
func ExitCodeFor ¶ added in v1.0.16
ExitCodeFor classifies a top-level error into one of the canonical exit codes (contract:cli.exit-codes v1). It is the only mapping main uses.
Classification order:
- nil -> ExitOK.
- An error exposing ExitCode() (ExitError, plugin ExitCodeError): that code.
- A *CLIError whose registry entry has Exit != 0: that Exit (E400 has 0 and falls through).
- The sentinel-table match with the highest class (auth > destructive > infra > user when sentinels are joined): the Exit of its registry code.
- Everything else: ExitUserError (1).
Returning ExitOK is reserved for nil errors and never inferred from classification.
func ExitWith ¶ added in v1.3.0
ExitWith returns an error that exits with code and reports err through the normal top-level error rendering.
func Register ¶ added in v1.4.13
func Register(entries ...CodeEntry)
Register adds entries to Registry. It is called from init() in a fragment file and never panics (Constitution §4.2).
Purpose: single entry point for contributing codes, so parallel Tickets each own one fragment file and never edit a shared table.
Inputs: entries with a Code, Summary-level fields, DocsPath and Exit.
Outputs: valid entries are stored (first registration wins). Every problem (bad code format, code outside every block, code in the reserved external block, code outside every owner range or from another owner's fragment, category that differs from the block's, duplicate code, invalid Exit) is appended to the problem list instead, naming the code and the fragment file(s). RegistryErrors returns that list and TestRegistryIntegrity fails on it.
Constraints: the fragment name is the base name of the calling source file.
func RegistryErrors ¶ added in v1.4.13
func RegistryErrors() []error
RegistryErrors returns every registration problem recorded so far: a duplicate code, a code outside its block, a mismatched category, and so on. It is empty when the committed fragments are consistent.
Types ¶
type Block ¶ added in v1.4.13
Block is one allocated range of error-code numbers and the single category every code in it carries (D13 of the P7-REG Epic, the canonical allocation).
Purpose: the category of a code is a function of its number; Register fills an empty Category from this table and rejects a mismatch.
Constraints: a new block needs a line in the Epic allocation table first; blocks never overlap and never reach the reserved external block.
type CLIError ¶ added in v1.0.6
type CLIError struct {
// Code is the error code (e.g., "E001"). Used for documentation cross-reference.
Code string
// What describes what happened in plain language.
What string
// Why explains the root cause.
Why string
// Fix provides exact steps the user can take to resolve the issue.
Fix string
// DocsPath is the relative docs URL path (e.g., "reference/error-codes#e001").
DocsPath string
// Wrapped is an optional underlying error for programmatic inspection.
Wrapped error
}
CLIError is the structured error type for all user-facing CLI errors. Every error shown to users must use this type to ensure consistent formatting with actionable guidance.
func New ¶ added in v1.0.6
New creates a new CLIError from a registered error code. If the code is not registered, it falls back to a generic error with the given message.
func (*CLIError) Error ¶ added in v1.0.6
Error implements the error interface with the structured 4-field format.
func (*CLIError) Unwrap ¶ added in v1.0.6
Unwrap returns the underlying error for errors.Is/As support.
type CodeEntry ¶ added in v1.0.6
type CodeEntry struct {
// Code is the error code, e.g. "E002". Set by the fragment; Register
// uses it as the Registry key.
Code string
// Category groups related errors (e.g., "docker", "config", "plugin").
// Optional in a fragment: it is derived from the code's block.
Category string
// Summary is a short description of this error class.
Summary string
// DefaultWhy is the default root-cause explanation.
DefaultWhy string
// DefaultFix is the default remediation steps.
DefaultFix string
// DocsPath is the docs URL path fragment.
DocsPath string
// Exit is the process exit status for this code (1 user, 2 infra, 3 auth,
// 4 destructive_blocked). 0 is valid only for E400.
Exit int
}
CodeEntry defines a registered error code: its identity, its default guidance fields, and the process exit class the code carries.
Purpose: one row of contract:cli.error-codes v1 and contract:cli.exit-codes v1. Fragment files (codes_<topic>.go) build CodeEntry values and pass them to Register from init().
Inputs: Code must match ^E[0-9]{3}$ and lie inside one block of the table in codes_blocks.go. Exit is one of ExitUserError..ExitDestructiveBlocked; 0 is allowed only on E400, where it means "classify by sentinel, else 1".
Outputs: the stored value is what Registry[code] returns. Register fills an empty Category from the code's block and always sets Code.
Constraints: a code is never renumbered or reused with a different meaning.
type Detail ¶ added in v1.4.13
type Detail struct {
Code string `json:"code"`
Message string `json:"message"`
Cause string `json:"cause,omitempty"`
Remediation string `json:"remediation,omitempty"`
DocsURL string `json:"docs_url,omitempty"`
ExitCode int `json:"exit_code"`
Class string `json:"class"`
}
Detail is the machine error object of contract:cli.error-codes v1. It is what the JSON error envelope carries under "error". JSON field order is the struct field order.
func Describe ¶ added in v1.4.13
Describe returns the machine error object for err, or nil when err is nil.
Purpose: the one function main and the JSON envelope call to turn any error into code, message, cause, remediation, docs link, exit status and class.
Inputs: any error. Precedence for the code: a *CLIError's Code, else the sentinel table's code for the matching sentinel of the highest class (auth, then destructive, then infra, then user), else E400.
Outputs: Message is the CLIError's What, else err.Error(). Cause and Remediation are the CLIError's Why and Fix; for a sentinel-derived code they are the registry defaults. DocsURL is https:// plus the DocsPath of the error, else of the registry entry. ExitCode equals ExitCodeFor(err), so it is the process exit status, and Class follows from it.
type ExitCoder ¶ added in v1.3.0
type ExitCoder interface{ ExitCode() int }
ExitCoder is implemented by errors that choose the process exit status. Both *ExitError and *plugin.ExitCodeError satisfy it, which lets main() and ExitCodeFor treat them uniformly without importing either package.
type ExitError ¶ added in v1.3.0
ExitError carries an explicit process exit code out of a command.
Purpose: let any RunE choose the process exit status without calling os.Exit, which the repo rule reserves for cmd/nself/main.go. Calling os.Exit inside a command skips deferred cleanup, skips the OTel span flush in PersistentPostRunE, and makes the path untestable because the test binary exits with it.
Inputs: a canonical code from this package plus an optional wrapped error.
Outputs: an error whose ExitCode() main() reads to set the exit status.
Constraints: a nil Err means "exit with this code and print nothing", which is the correct shape when the command already wrote its own diagnostics.
func (*ExitError) ExitCode ¶ added in v1.3.0
ExitCode reports the process exit status this error requests.
type Owner ¶ added in v1.4.13
type Owner struct {
Lo, Hi int
Who string // Ticket id, e.g. "P7-PLUG-01"
Fragment string // base name of the fragment file, e.g. "codes_plugin_manifest.go"
}
Owner is a sub-range of a block assigned to one Ticket and the one fragment file that may register codes in it.
Purpose: block ownership as data. Register records a problem for a code that lies in no Owner range (spare or free numbers fail until the lead adds a line to the Epic table and here) or that is registered from a fragment other than the owner's. A test proves the ranges are disjoint and nested inside one block.
Source Files
¶
- codes.go
- codes_acme.go
- codes_archguard.go
- codes_backup.go
- codes_backup_key.go
- codes_blocks.go
- codes_bundle_install.go
- codes_bundle_remove.go
- codes_canon.go
- codes_cli.go
- codes_compat.go
- codes_config.go
- codes_config_explain.go
- codes_custom_service.go
- codes_database.go
- codes_deploy.go
- codes_deploy_env.go
- codes_docker.go
- codes_domain.go
- codes_export.go
- codes_gate.go
- codes_health.go
- codes_httpapi.go
- codes_images.go
- codes_importer.go
- codes_init.go
- codes_invoke.go
- codes_lock.go
- codes_mount.go
- codes_nself_yaml.go
- codes_object_storage.go
- codes_oplock.go
- codes_pg_requires.go
- codes_plugin.go
- codes_plugin_cli_collision.go
- codes_plugin_fragment.go
- codes_plugin_manifest.go
- codes_plugin_migrate.go
- codes_plugin_seed.go
- codes_plugin_track.go
- codes_portable.go
- codes_promote.go
- codes_proxy.go
- codes_reconcile.go
- codes_registry_surface.go
- codes_secret_resolve.go
- codes_ssl.go
- codes_update_stack.go
- codes_vector_search.go
- describe.go
- errs.go
- exit_codes.go
- exit_error.go
- sentinels.go
- structured.go