Skip to main content
The Auth0 Go SDK provides structured error types for both the Management API and Authentication API. These error types contain detailed information about what went wrong and how to handle different error scenarios.

Authentication API Errors

Error Type

type Error struct {
    StatusCode int    `json:"statusCode"`
    Err        string `json:"error"`
    Message    string `json:"error_description"`
    MFAToken   string `json:"mfa_token,omitempty"`
}
Represents errors returned from the Authentication API. The Err property can be used to check the error code returned from the API.

Methods

Error

func (a *Error) Error() string
Formats the error into a string representation. Returns: A formatted string in the format: "<StatusCode> <Err>: <Message>" Example:
import "github.com/auth0/go-auth0/v2/authentication"

token, err := authAPI.LoginWithPassword(ctx, request)
if err != nil {
    if authErr, ok := err.(*authentication.Error); ok {
        fmt.Println(authErr.Error())
        // Output: "401 invalid_grant: Wrong email or password."
    }
}

Status

func (a *Error) Status() int
Returns the status code of the error. Example:
import "github.com/auth0/go-auth0/v2/authentication"

token, err := authAPI.LoginWithPassword(ctx, request)
if err != nil {
    if authErr, ok := err.(*authentication.Error); ok {
        statusCode := authErr.Status()
        if statusCode == 401 {
            // Handle unauthorized error
        }
    }
}

GetMFAToken

func (a *Error) GetMFAToken() string
Returns the MFA token associated with the error, if any. Returns an empty string if the error is nil or if there is no MFA token. Example:
import "github.com/auth0/go-auth0/v2/authentication"

token, err := authAPI.LoginWithPassword(ctx, request)
if err != nil {
    if authErr, ok := err.(*authentication.Error); ok {
        if mfaToken := authErr.GetMFAToken(); mfaToken != "" {
            // MFA is required, proceed with MFA flow
            fmt.Println("MFA token:", mfaToken)
        }
    }
}

Common Authentication Error Codes

Error CodeDescription
invalid_grantWrong email or password, or user is blocked
invalid_requestMissing required parameter or invalid request format
unauthorizedInvalid or expired token
access_deniedUser denied authorization
mfa_requiredMulti-factor authentication is required
invalid_user_passwordPassword does not meet policy requirements
password_leakedPassword has been leaked and cannot be used

Management API Errors

The Management API uses HTTP status code-based error types. All error types embed *core.APIError and contain a Body field with the error details.

BadRequestError (400)

type BadRequestError struct {
    *core.APIError
    Body interface{}
}
Invalid request URI. The message will vary depending on the cause. Example:
import "github.com/auth0/go-auth0/v2/management"

client, err := api.Client.Create(ctx, &management.Client{
    Name: auth0.String(""), // Empty name
})
if err != nil {
    if badReq, ok := err.(*management.BadRequestError); ok {
        fmt.Println("Bad request:", badReq.Body)
    }
}

UnauthorizedError (401)

type UnauthorizedError struct {
    *core.APIError
    Body interface{}
}
Invalid token. Example:
import "github.com/auth0/go-auth0/v2/management"

client, err := api.Client.Read(ctx, clientID)
if err != nil {
    if unauth, ok := err.(*management.UnauthorizedError); ok {
        // Token is invalid or expired, refresh your token
        fmt.Println("Unauthorized:", unauth.Body)
    }
}

PaymentRequiredError (402)

type PaymentRequiredError struct {
    *core.APIError
    Body interface{}
}
A paid subscription is required for this feature.

ForbiddenError (403)

type ForbiddenError struct {
    *core.APIError
    Body interface{}
}
Insufficient scope. For example: “Insufficient scope, expected: read:actions.” Example:
import "github.com/auth0/go-auth0/v2/management"

action, err := api.Action.Read(ctx, actionID)
if err != nil {
    if forbidden, ok := err.(*management.ForbiddenError); ok {
        // Token does not have required scopes
        fmt.Println("Forbidden:", forbidden.Body)
    }
}

NotFoundError (404)

type NotFoundError struct {
    *core.APIError
    Body interface{}
}
The requested resource does not exist. Example:
import "github.com/auth0/go-auth0/v2/management"

client, err := api.Client.Read(ctx, "invalid-id")
if err != nil {
    if notFound, ok := err.(*management.NotFoundError); ok {
        fmt.Println("Client not found:", notFound.Body)
    }
}

ConflictError (409)

type ConflictError struct {
    *core.APIError
    Body interface{}
}
A resource with the same identifier already exists. For example, an action module with the same name. Example:
import "github.com/auth0/go-auth0/v2/management"

client, err := api.Client.Create(ctx, &management.Client{
    Name: auth0.String("Existing Client"),
})
if err != nil {
    if conflict, ok := err.(*management.ConflictError); ok {
        fmt.Println("Resource already exists:", conflict.Body)
    }
}

PreconditionFailedError (412)

type PreconditionFailedError struct {
    *core.APIError
    Body interface{}
}
The resource cannot be modified or deleted because it is in use. For example: “The Actions Module cannot be deleted because it is in use by one or more actions.”

ContentTooLargeError (413)

type ContentTooLargeError struct {
    *core.APIError
    Body interface{}
}
Payload content length greater than maximum allowed: 512000 bytes.

TooManyRequestsError (429)

type TooManyRequestsError struct {
    *core.APIError
    Body interface{}
}
Too many requests. Check the X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. Example:
import (
    "time"
    "github.com/auth0/go-auth0/v2/management"
)

client, err := api.Client.Read(ctx, clientID)
if err != nil {
    if rateLimit, ok := err.(*management.TooManyRequestsError); ok {
        // Implement exponential backoff or wait
        fmt.Println("Rate limited:", rateLimit.Body)
        time.Sleep(1 * time.Minute)
    }
}

InternalServerError (500)

type InternalServerError struct {
    *core.APIError
    Body interface{}
}
Internal error on the Auth0 server.

ServiceUnavailableError (503)

type ServiceUnavailableError struct {
    *core.APIError
    Body interface{}
}
The query exceeded the timeout. Please try refining your search criteria. See Search Best Practices.

Error Handling Patterns

Type Assertion

Use type assertion to check for specific error types:
import "github.com/auth0/go-auth0/v2/management"

client, err := api.Client.Read(ctx, clientID)
if err != nil {
    switch e := err.(type) {
    case *management.NotFoundError:
        fmt.Println("Client not found")
    case *management.UnauthorizedError:
        fmt.Println("Authentication failed")
    case *management.ForbiddenError:
        fmt.Println("Insufficient permissions")
    case *management.TooManyRequestsError:
        fmt.Println("Rate limited")
    default:
        fmt.Printf("Unknown error: %v\n", err)
    }
}

Unwrapping Errors

All Management API errors implement the Unwrap() method, allowing you to access the underlying *core.APIError:
import (
    "errors"
    "github.com/auth0/go-auth0/v2/management"
    "github.com/auth0/go-auth0/v2/management/core"
)

client, err := api.Client.Read(ctx, clientID)
if err != nil {
    var apiErr *core.APIError
    if errors.As(err, &apiErr) {
        fmt.Printf("API Error: Status %d\n", apiErr.StatusCode)
    }
}

Checking Status Codes

For Authentication API errors, check the status code directly:
import "github.com/auth0/go-auth0/v2/authentication"

token, err := authAPI.LoginWithPassword(ctx, request)
if err != nil {
    if authErr, ok := err.(*authentication.Error); ok {
        switch authErr.Status() {
        case 401:
            fmt.Println("Invalid credentials")
        case 429:
            fmt.Println("Too many login attempts")
        case 500:
            fmt.Println("Server error")
        }
    }
}

Checking Error Codes

For Authentication API errors, check the error code for specific conditions:
import "github.com/auth0/go-auth0/v2/authentication"

token, err := authAPI.LoginWithPassword(ctx, request)
if err != nil {
    if authErr, ok := err.(*authentication.Error); ok {
        switch authErr.Err {
        case "mfa_required":
            // Handle MFA flow
            mfaToken := authErr.GetMFAToken()
            // Proceed with MFA challenge
        case "password_leaked":
            // Force password reset
        case "invalid_grant":
            // Invalid credentials
        }
    }
}

Best Practices

  1. Always check for errors: Never ignore errors returned by SDK methods
  2. Use type assertions for specific handling: Use type switches or type assertions to handle different error types appropriately
  3. Handle rate limiting gracefully: Implement exponential backoff when encountering TooManyRequestsError
  4. Check MFA requirements: For Authentication API calls, always check for MFA tokens when handling errors
  5. Log error details: Log the full error body for debugging, but be careful not to log sensitive information
  6. Implement retries carefully: Only retry idempotent operations and implement proper backoff strategies
  7. Handle 404 errors appropriately: A NotFoundError might be expected in some scenarios (e.g., checking if a resource exists)

Example: Comprehensive Error Handling

import (
    "context"
    "fmt"
    "time"
    "github.com/auth0/go-auth0/v2"
    "github.com/auth0/go-auth0/v2/management"
)

func getClientWithRetry(api *management.Management, ctx context.Context, clientID string) (*management.Client, error) {
    maxRetries := 3
    for i := 0; i < maxRetries; i++ {
        client, err := api.Client.Read(ctx, clientID)
        if err == nil {
            return client, nil
        }

        switch e := err.(type) {
        case *management.NotFoundError:
            // Client doesn't exist, no point retrying
            return nil, fmt.Errorf("client not found: %s", clientID)

        case *management.UnauthorizedError:
            // Auth failed, no point retrying without new credentials
            return nil, fmt.Errorf("authentication failed")

        case *management.TooManyRequestsError:
            // Rate limited, wait and retry
            if i < maxRetries-1 {
                waitTime := time.Duration(i+1) * time.Second
                fmt.Printf("Rate limited, waiting %v before retry\n", waitTime)
                time.Sleep(waitTime)
                continue
            }
            return nil, fmt.Errorf("rate limited after %d retries", maxRetries)

        case *management.InternalServerError:
            // Server error, might be transient, retry
            if i < maxRetries-1 {
                fmt.Printf("Server error, retrying (attempt %d/%d)\n", i+1, maxRetries)
                time.Sleep(time.Second)
                continue
            }
            return nil, fmt.Errorf("server error after %d retries", maxRetries)

        default:
            // Unknown error
            return nil, fmt.Errorf("unexpected error: %v", err)
        }
    }

    return nil, fmt.Errorf("failed after %d retries", maxRetries)
}

See Also

Build docs developers (and LLMs) love