Files
GitCaddy 6f7e600645
Some checks failed
Build and Release / Create Release (push) Has been skipped
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 2m28s
Build and Release / Unit Tests (push) Successful in 2m31s
Build and Release / Lint (push) Failing after 2m57s
Build and Release / Build Binaries (amd64, darwin) (push) Has been skipped
Build and Release / Build Binaries (amd64, linux) (push) Has been skipped
Build and Release / Build Binaries (amd64, windows) (push) Has been skipped
Build and Release / Build Binaries (arm64, darwin) (push) Has been skipped
Build and Release / Build Binaries (arm64, linux) (push) Has been skipped
chore: update copyright headers to MarketAlly
- New files: Copyright 2026 MarketAlly
- Modified files: Copyright YYYY The Gitea Authors and MarketAlly

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 22:56:56 +00:00

130 lines
3.5 KiB
Go

// Copyright 2026 MarketAlly. All rights reserved.
// SPDX-License-Identifier: MIT
package errors
import (
"fmt"
"code.gitea.io/gitea/modules/setting"
)
// APIErrorResponse is the top-level error response wrapper
type APIErrorResponse struct {
Error *APIError `json:"error"`
}
// APIError represents a structured API error following RFC 7807 Problem Details
// with additional fields for AI-friendly error handling
type APIError struct {
// Machine-readable error code (e.g., "REPO_NOT_FOUND")
Code string `json:"code"`
// Human-readable error message
Message string `json:"message"`
// HTTP status code
Status int `json:"status"`
// Additional context about the error
Details map[string]any `json:"details,omitempty"`
// URL to documentation about this error
DocumentationURL string `json:"documentation_url,omitempty"`
// Unique request ID for tracing
RequestID string `json:"request_id,omitempty"`
// Suggested actions or alternatives
Suggestions []string `json:"suggestions,omitempty"`
// RFC 7807 Problem Details fields
Type string `json:"type,omitempty"` // URI reference identifying the problem type
Title string `json:"title,omitempty"` // Short summary of the problem type
Instance string `json:"instance,omitempty"` // URI reference for this specific occurrence
}
// NewAPIError creates a new structured API error
func NewAPIError(code ErrorCode, requestID string) *APIError {
docURL := fmt.Sprintf("%s/api/errors#%s", setting.AppURL, code)
return &APIError{
Code: code.String(),
Message: code.Message(),
Status: code.HTTPStatus(),
DocumentationURL: docURL,
RequestID: requestID,
Type: "about:blank",
Title: code.Message(),
Instance: requestID,
}
}
// WithDetails adds details to the error
func (e *APIError) WithDetails(details map[string]any) *APIError {
e.Details = details
return e
}
// WithDetail adds a single detail to the error
func (e *APIError) WithDetail(key string, value any) *APIError {
if e.Details == nil {
e.Details = make(map[string]any)
}
e.Details[key] = value
return e
}
// WithMessage overrides the default message
func (e *APIError) WithMessage(message string) *APIError {
e.Message = message
e.Title = message
return e
}
// WithSuggestions adds suggested actions
func (e *APIError) WithSuggestions(suggestions ...string) *APIError {
e.Suggestions = append(e.Suggestions, suggestions...)
return e
}
// Response wraps the error in an APIErrorResponse
func (e *APIError) Response() *APIErrorResponse {
return &APIErrorResponse{Error: e}
}
// ValidationError represents a field-level validation error
type ValidationError struct {
Field string `json:"field"`
Message string `json:"message"`
Code string `json:"code,omitempty"`
}
// APIValidationError represents a validation error with field-level details
type APIValidationError struct {
*APIError
Errors []ValidationError `json:"errors,omitempty"`
}
// NewValidationError creates a new validation error
func NewValidationError(requestID string, errors ...ValidationError) *APIValidationError {
baseErr := NewAPIError(ValInvalidInput, requestID)
return &APIValidationError{
APIError: baseErr,
Errors: errors,
}
}
// AddFieldError adds a field validation error
func (e *APIValidationError) AddFieldError(field, message string, code ...string) *APIValidationError {
ve := ValidationError{
Field: field,
Message: message,
}
if len(code) > 0 {
ve.Code = code[0]
}
e.Errors = append(e.Errors, ve)
return e
}