errtax

package
v0.14.2 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package errtax is the CLI's error taxonomy: the stable error types and codes the JSON envelope emits, and the registry that binds every code to its classification. It is a stdlib-only leaf so jira, config, adf, issuekey, and cli can all describe their errors with a Code without import cycles; the cli error mapper derives everything else from here.

Registry

The registry is the single source of truth for code → {type, exit, hint, retryable}. An error carries only its Code; Lookup supplies the rest. Rows are declared once in a composite literal and never mutated. The taxonomy guard test enumerates Codes and holds the registry to the frozen, human-reviewed contract table, so a new code cannot ship without a reviewed row.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExitFor

func ExitFor(t Type) int

ExitFor returns a type's default process exit code. TypeUnknown and any unrecognized type fail closed to the server exit.

func HintFor

func HintFor(c Code) string

HintFor returns the code's canonical hint, or the generic rerun-with---debug fallback for an unregistered code — never an empty string.

Types

type Candidated

type Candidated interface{ CandidateRows() []map[string]any }

Candidated carries structured disambiguation rows for the envelope's candidates[] field. The method is CandidateRows, not Candidates: implementers carry a Candidates field.

type Code

type Code string

Code is the stable snake_case error code the envelope's `code` field carries. Agents branch on Code, never on message text; every code has a registry row.

const (
	CodeFlagUnknown Code = "flag_unknown"
	// CodeFlagForeign is a recognized flag from a different Jira CLI — not
	// a typo, so it gets an orientation hint instead of a spelling one;
	// this CLI's equivalents ride the envelope's suggestions field.
	CodeFlagForeign         Code = "flag_foreign"
	CodeFlagValueMissing    Code = "flag_value_missing"
	CodeFlagValueInvalid    Code = "flag_value_invalid"
	CodeFlagSyntaxInvalid   Code = "flag_syntax_invalid"
	CodeRequiredFlagMissing Code = "required_flag_missing"
	CodeArgCountInvalid     Code = "arg_count_invalid"
	CodeArgValueInvalid     Code = "arg_value_invalid"
	// CodeIssueTypeUnknown is a --type value that names no issue type on the
	// project's create screen. The CLI resolves the type against the fetched
	// list in-code, so a miss is a bad input value (validation, exit 3), not a
	// Jira 404 — the valid names ride the envelope's suggestions field.
	CodeIssueTypeUnknown Code = "issue_type_unknown"
	// CodeAgentTopicUnknown is an agent-surface lookup that matched
	// nothing: a guide slug, guide section, schema --path, or export
	// format the discovery surface does not carry. The surface lists its
	// own valid names, so the hint routes there rather than to --help.
	CodeAgentTopicUnknown Code = "agent_topic_unknown"

	// CodeSavedQueryUnknown is a `search saved NAME` value that matches no
	// saved query. The names live in the user's queries directory, not in
	// --help, so this gets its own hint rather than reusing arg_value_invalid.
	CodeSavedQueryUnknown Code = "saved_query_unknown"
	// CodeJQExpressionInvalid is a --jq expression gojq could not parse or
	// compile — a bad program, not bad data, so the hint points at the
	// expression.
	CodeJQExpressionInvalid Code = "jq_expression_invalid"
	// CodeJQOutputConflict is --jq combined with an explicit --output=human:
	// the filter runs over JSON output, so the two requests contradict.
	CodeJQOutputConflict Code = "jq_output_conflict"
	// CodeJQEvalFailed is a --jq expression that compiled but failed while
	// running against the emitted document (a type error, a halt_error).
	CodeJQEvalFailed Code = "jq_eval_failed"
	// CodeRankRejected is the agile rank endpoint's 400: Jira refused the
	// rank itself — typically a project with no Jira Software board (no
	// LexoRank field) or an unusable anchor.
	CodeRankRejected Code = "rank_rejected"
	// CodeRankPartial is the rank endpoint's 207: some issues ranked, the
	// entries named in the envelope did not.
	CodeRankPartial             Code = "rank_partial"
	CodeCommandUnknown          Code = "command_unknown"
	CodePromptAborted           Code = "prompt_aborted"
	CodePromptCanceled          Code = "prompt_canceled"
	CodePromptUnavailable       Code = "prompt_unavailable"
	CodeMarkdownLossyConversion Code = "markdown_lossy_conversion"
	CodeReadOnly                Code = "read_only"
	CodeADFInvalid              Code = "adf_invalid"
	CodeIssueKeyExpansionLimit  Code = "issue_key_expansion_limit"
	CodeUserAmbiguous           Code = "user_ambiguous"
	CodeBoardAmbiguous          Code = "board_ambiguous"
	CodeDryRunBlocked           Code = "dry_run_blocked"
	// CodeCredentialEmpty, CodeCredentialNamespaceCollision, and
	// CodeOnePasswordItemAmbiguous classify as validation, matching their
	// construction sites: an empty token, an unusable profile name, and an
	// ambiguous 1Password item are input problems — the fix is "correct
	// your input", not "re-authenticate". The ambiguity code is the
	// credential-side parallel of user_ambiguous and board_ambiguous.
	CodeCredentialEmpty              Code = "credential_empty"
	CodeCredentialNamespaceCollision Code = "credential_namespace_collision"
	CodeOnePasswordItemAmbiguous     Code = "onepassword_item_ambiguous"
	// CodeEnvBackendReadOnly: a write or delete was attempted against the env
	// secret backend, which only ever reads its JIRA_TOKEN_* variable.
	CodeEnvBackendReadOnly Code = "env_backend_read_only"
	// CodeValidationFailed is the validation catch-all; every specific
	// validation code above must pre-empt it.
	CodeValidationFailed Code = "validation_failed"
	// CodeJiraBadRequest (400) and CodeJiraConflict (409) classify as
	// validation deliberately: both are client-actionable — correct the
	// input, or re-fetch and retry — where a server type would read as an
	// upstream fault.
	CodeJiraBadRequest Code = "jira_bad_request"
	CodeJiraConflict   Code = "jira_conflict"
)

Validation codes (exit 3): command-line input, prompts, payload shape, and the transport-layer mutation guards.

const (
	CodeJiraUnauthorized             Code = "jira_unauthorized"
	CodeJiraForbidden                Code = "jira_forbidden"
	CodeCredentialMissing            Code = "credential_missing"
	CodeCredentialSourceConflict     Code = "credential_source_conflict"
	CodeCredentialBackendUnavailable Code = "credential_backend_unavailable"
	CodeCredentialMigrationFailed    Code = "credential_migration_failed"
	CodeCredentialCleanupFailed      Code = "credential_cleanup_failed"
	CodeOnePasswordUnavailable       Code = "onepassword_unavailable"
	// CodeCredentialRejected is a login-verification rejection: Jira said
	// the email/token pair is wrong.
	CodeCredentialRejected Code = "credential_rejected"
	// CodeCredentialVerifyUnavailable: Jira could not be reached to verify
	// a credential at login — distinct from the credential store being
	// unreachable (credential_backend_unavailable).
	CodeCredentialVerifyUnavailable Code = "credential_verify_unavailable"
	// CodeOnePasswordUnsupportedBuild: the binary was built without CGO,
	// so 1Password support is compiled out entirely.
	CodeOnePasswordUnsupportedBuild Code = "onepassword_unsupported_build"
	// CodeKeyringUnavailable: the OS keyring cannot service requests at all —
	// no Secret Service on the D-Bus (WSL, headless Linux), an unsupported
	// platform — distinct from credential_backend_unavailable, whose hint
	// assumes the backend exists and merely hiccuped.
	CodeKeyringUnavailable Code = "keyring_unavailable"
	// CodeEnvCredentialUnset: a profile using the env secret backend has no
	// JIRA_TOKEN_* variable set — the credential's single source is absent.
	CodeEnvCredentialUnset Code = "env_credential_unset"
	// CodeAuthFailed is the auth catch-all for untyped credential failures.
	CodeAuthFailed Code = "auth_failed"
)

Auth codes (exit 1): rejected or unusable credentials, whether Jira said so (jira_*) or the local credential machinery did (credential_*).

const (
	// CodeProfileNotDefined and CodeProfileIncomplete split the profile
	// failure by remediation — create the profile vs finish setting it
	// up. Both classify as not_found so a bad --profile fails closed.
	CodeProfileNotDefined Code = "profile_not_defined"
	CodeProfileIncomplete Code = "profile_incomplete"
	CodeJiraNotFound      Code = "jira_not_found"
	// CodeJiraSiteNotFound: the base URL names no Atlassian tenant at all —
	// a 404 carrying the edge's Atl-Missing-Tcs signal. Distinct from
	// jira_not_found (a missing resource inside a real site) because the
	// remediation is fixing the profile's site name, not the identifier.
	CodeJiraSiteNotFound Code = "jira_site_not_found"
	// CodeJiraGone (410) is a permanently deleted resource: not-found tells
	// an agent to fix the reference, where validation would suggest
	// correcting the request.
	CodeJiraGone Code = "jira_gone"
	// CodeNotFound is the not-found catch-all for untyped failures.
	CodeNotFound Code = "not_found"
)

Not-found codes (exit 2).

const (
	CodeJiraRateLimited Code = "jira_rate_limited"
	// CodeRateLimited is the rate-limit catch-all for untyped failures.
	CodeRateLimited Code = "rate_limited"
)

Rate-limit codes (exit 4).

const (
	CodeJiraServerError Code = "jira_server_error"
	// CodeServerError is the server catch-all for untyped failures.
	CodeServerError Code = "server_error"
	CodeCanceled    Code = "canceled"
	CodeTimeout     Code = "timeout"
)

Server codes (exit 5), plus the two lifecycle codes that pin their own exits: canceled (6) and timeout (7) so a caller can distinguish an interrupted or expired invocation from a real backend failure.

const CodeUnknown Code = ""

CodeUnknown is the zero value — Lookup misses on it, so an unclassified error fails closed to the server type and generic hint.

func Codes

func Codes() []Code

Codes returns every registered code as a freshly allocated, sorted, non-nil slice; the registry itself is never exposed or reordered.

func DefaultCode

func DefaultCode(t Type) Code

DefaultCode returns a type's catch-all code — the code an untyped or unmapped failure of that type falls back to. TypeUnknown falls back to the server catch-all.

type Coded

type Coded interface {
	error
	// Code returns the stable envelope code this error classifies as.
	Code() Code
}

Coded is the minimal contract a taxonomy-aware error satisfies: it names its own Code, and the registry supplies type, exit, hint, and retryability. The name deliberately opts out of the -er convention — Code is a getter, not an action.

type Flagger

type Flagger interface{ FlagName() string }

Flagger names the command-line flag a validation failure is scoped to. The method is FlagName, not Flag: implementers carry a Flag field.

type Spec

type Spec struct {
	// Type is the coarse classification the envelope's `type` field carries.
	Type Type
	// Exit is the process exit code for this code — usually the type's
	// default, pinned per code so canceled (6) and timeout (7) can diverge
	// from their server type.
	Exit int
	// Hint is the next-action remediation, in the plain words a person
	// would use. Never empty, and always static: a runtime specific
	// belongs in the error message or a structured envelope field.
	Hint string
	// Retryable reports whether retrying the same invocation could succeed.
	Retryable bool
}

Spec is one registry row: everything the envelope derives from a code.

func Lookup

func Lookup(c Code) (Spec, bool)

Lookup returns the registry row for a code. ok is false for an unregistered code (including CodeUnknown); callers then fail closed to the server type, exit 5, and the generic hint.

type Type

type Type string

Type is the coarse error classification the envelope's `type` field carries. Each type owns one default process exit code (see ExitFor); individual codes may pin their own exit in the registry.

const (
	// TypeUnknown is the zero value — never emitted; it marks an
	// unclassified error before the registry resolves it.
	TypeUnknown    Type = ""
	TypeAuth       Type = "auth"
	TypeNotFound   Type = "not_found"
	TypeValidation Type = "validation"
	TypeRateLimit  Type = "rate_limit"
	TypeServer     Type = "server"
)

The five envelope error types, plus the named zero value.

Jump to

Keyboard shortcuts

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