Files
headscale/hscontrol/api/v1/errors.go
T
Kristoffer Dalby f2df44295a state, db: validate and store the current policy before installing it
Reject empty input. Validate without changing live state, then store and
install under one lock; prune old rows only with a successful write.
2026-11-02 19:15:40 +01:00

62 lines
2.1 KiB
Go

package apiv1
import (
"errors"
"github.com/danielgtaylor/huma/v2"
"github.com/juanfont/headscale/hscontrol/db"
"github.com/juanfont/headscale/hscontrol/state"
"github.com/juanfont/headscale/hscontrol/types"
"gorm.io/gorm"
)
// mapError translates a state/db-layer error into a Huma HTTP error
// (NotFound→404, invalid input→400, conflict→409, everything else→500).
// Handlers use this default mapping and may return a more specific huma.ErrorN
// directly. msg is a human context prefix, e.g. "getting node".
func mapError(msg string, err error) error {
if err == nil {
return nil
}
switch {
case errors.Is(err, types.ErrRegistrationPayloadTooLarge):
return huma.Error413RequestEntityTooLarge(msg, err)
case errors.Is(err, state.ErrAuthCacheFull),
errors.Is(err, state.ErrAuthCacheClosed):
return huma.Error503ServiceUnavailable(msg, err)
case errors.Is(err, gorm.ErrRecordNotFound),
errors.Is(err, state.ErrNodeNotFound),
errors.Is(err, state.ErrNodeNotInNodeStore),
errors.Is(err, db.ErrUserNotFound),
errors.Is(err, db.ErrNodeNotFoundRegistrationCache),
errors.Is(err, state.ErrRegistrationExpired):
return huma.Error404NotFound(msg, err)
case errors.Is(err, state.ErrGivenNameInvalid),
errors.Is(err, state.ErrGivenNameTaken),
errors.Is(err, state.ErrNodeNameNotUnique),
errors.Is(err, state.ErrNodeMarkedTaggedButHasNoTags),
errors.Is(err, state.ErrNodeHasNeitherUserNorTags),
errors.Is(err, state.ErrRequestedTagsInvalidOrNotPermitted),
errors.Is(err, types.ErrExpiryOutOfRange),
errors.Is(err, types.ErrHostinfoTooLarge),
errors.Is(err, db.ErrUserStillHasNodes),
errors.Is(err, db.ErrCannotChangeOIDCUser),
errors.Is(err, db.ErrPreAuthKeyNotTaggedOrOwned),
errors.Is(err, db.ErrSingleUseAuthKeyHasBeenUsed),
errors.Is(err, state.ErrInvalidPolicy):
return huma.Error400BadRequest(msg, err)
case errors.Is(err, state.ErrNodeKeyInUse),
errors.Is(err, state.ErrAmbiguousNodeOwnership),
errors.Is(err, state.ErrAuthCacheEntryExists):
return huma.Error409Conflict(msg, err)
default:
return huma.Error500InternalServerError(msg, err)
}
}