From claude-resources
Go error handling patterns. Wrapping with fmt.Errorf, sentinel errors, custom types, errors.Is/As, HTTP error mapping. Extends core/error-handling with Go-specific implementations.
npx claudepluginhub deandum/claude-resources --plugin go-skillsThis skill uses the workspace's default tool permissions.
Errors are values. Use `fmt.Errorf` with `%w` for wrapping. Check with `errors.Is`/`errors.As`.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides agent creation for Claude Code plugins with file templates, frontmatter specs (name, description, model), triggering examples, system prompts, and best practices.
Errors are values. Use fmt.Errorf with %w for wrapping. Check with errors.Is/errors.As.
// Default: wrap with context as you propagate up
return fmt.Errorf("finding user %s: %w", id, err)
%w to preserve chain for errors.Is/errors.As"finding user %s" not "error in FindByID"var (
ErrNotFound = errors.New("not found")
ErrAlreadyExists = errors.New("already exists")
ErrForbidden = errors.New("forbidden")
)
Check with errors.Is(err, ErrNotFound).
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation: %s: %s", e.Field, e.Message)
}
Extract with errors.As:
var valErr *ValidationError
if errors.As(err, &valErr) {
writeJSON(w, http.StatusBadRequest, map[string]string{
"field": valErr.Field, "message": valErr.Message,
})
return
}
func (c *Config) Validate() error {
var errs []error
if c.Addr == "" {
errs = append(errs, fmt.Errorf("addr is required"))
}
if c.Timeout <= 0 {
errs = append(errs, fmt.Errorf("timeout must be positive"))
}
return errors.Join(errs...)
}
errors.Join returns a single error that wraps all non-nil inputs. Callers can check for specific sentinels via errors.Is (which walks the full tree of joined errors). To enumerate all wrapped errors individually, type-assert to the interface{ Unwrap() []error } interface:
err := cfg.Validate()
if err != nil {
if joined, ok := err.(interface{ Unwrap() []error }); ok {
for _, e := range joined.Unwrap() {
logger.Error("config validation failed", "error", e)
}
}
return err
}
Use this when the caller needs to report each failure individually (e.g., writing field-level validation errors to an HTTP response).
Map domain errors to HTTP responses at the boundary:
func (h *Handler) handleError(w http.ResponseWriter, r *http.Request, err error) {
switch {
case errors.Is(err, domain.ErrNotFound):
writeJSON(w, http.StatusNotFound, errorResponse("not found"))
case errors.Is(err, domain.ErrForbidden):
writeJSON(w, http.StatusForbidden, errorResponse("forbidden"))
default:
var valErr *domain.ValidationError
if errors.As(err, &valErr) {
writeJSON(w, http.StatusBadRequest, valErr)
return
}
h.logger.Error("unhandled error", "error", err, "path", r.URL.Path)
writeJSON(w, http.StatusInternalServerError, errorResponse("internal error"))
}
}
// Package order manages order lifecycle operations.
//
// Errors:
// - ErrNotFound: the requested order does not exist
// - ErrAlreadyShipped: cannot modify shipped order
// - *ValidationError: invalid order data (check Field and Message)
package order
Must* acceptable only in main() or test setuperr return must be checkederrors.Is/errors.As, never strings.Contains(err.Error(), ...)"querying user %s: %w" not "error in FindByID: failed to query: %w"go vet ./... passes with no diagnosticsreturn err — all errors wrapped with fmt.Errorf("context: %w", err)errors.Is/errors.As used for error checks (no strings.Contains(err.Error(), ...))