Skip to main content
The ErrorOrX generator and analyzer emit diagnostics to help catch issues at compile time.

Endpoint Diagnostics

Handler Structure

IDSeverityDescription
EOE001ErrorInvalid return type - must return ErrorOr<T>
EOE002ErrorHandler must be static
EOE017ErrorAnonymous return type not supported
EOE020ErrorInaccessible type (private/protected) in endpoint
EOE021ErrorType parameter not supported in return type

Route Validation

IDSeverityDescription
EOE003ErrorRoute parameter not bound to method parameter
EOE004ErrorDuplicate route pattern detected
EOE005ErrorInvalid route pattern syntax
EOE023WarningRoute constraint type mismatch (e.g., {id:int} with string param)

Parameter Binding

IDSeverityDescription
EOE006ErrorMultiple body sources on single endpoint
EOE009Warning[FromBody] on GET/DELETE method
EOE011ErrorInvalid [FromRoute] type
EOE012ErrorInvalid [FromQuery] type
EOE013ErrorInvalid [AsParameters] type
EOE014Error[AsParameters] type has no accessible constructor
EOE016ErrorInvalid [FromHeader] type
EOE018ErrorNested [AsParameters] not supported
EOE019ErrorNullable [AsParameters] not supported
EOE025ErrorAmbiguous parameter binding (GET/DELETE + complex type)

AOT & Serialization

IDSeverityDescription
EOE007WarningType not AOT-serializable
EOE030InfoToo many result types for Results<> union (max 6)
EOE032WarningUnknown error factory method
EOE033ErrorUndocumented interface call
EOE040WarningMissing CamelCase JSON policy on user’s JsonSerializerContext
EOE041ErrorMissing JsonSerializerContext for AOT with [FromBody]

Response Attributes

IDSeverityDescription
EOE010Warning[AcceptedResponse] on GET/DELETE method

API Versioning Diagnostics

IDSeverityDescription
EOE050Warning[ApiVersionNeutral] and [MapToApiVersion] are mutually exclusive
EOE051Warning[MapToApiVersion] references undeclared version
EOE052WarningAsp.Versioning.Http package not referenced
EOE053InfoEndpoint missing versioning when others use it
EOE054ErrorInvalid API version format
EOE055WarningDuplicate route parameter binding
API versioning support requires the Asp.Versioning.Http package. See the API Versioning guide for setup instructions.

Common Fixes

EOE001: Invalid Return Type

// ❌ Wrong
[Get("/todos")]
public static List<Todo> GetAll() => _db.GetAll();

// ✅ Correct
[Get("/todos")]
public static ErrorOr<List<Todo>> GetAll() => _db.GetAll();

EOE002: Handler Must Be Static

// ❌ Wrong
public class TodoEndpoints
{
    [Get("/todos")]
    public ErrorOr<List<Todo>> GetAll() => ...
}

// ✅ Correct
public static class TodoEndpoints
{
    [Get("/todos")]
    public static ErrorOr<List<Todo>> GetAll() => ...
}

EOE003: Route Parameter Not Bound

// ❌ Wrong - 'id' in route but not in params
[Get("/todos/{id}")]
public static ErrorOr<Todo> Get() => ...

// ✅ Correct
[Get("/todos/{id}")]
public static ErrorOr<Todo> Get(Guid id) => ...

EOE004: Duplicate Route

// ❌ Wrong - same route pattern
[Get("/todos/{id}")]
public static ErrorOr<Todo> GetById(Guid id) => ...

[Get("/todos/{todoId}")]  // EOE004: Duplicate of /todos/{id}
public static ErrorOr<Todo> GetByTodoId(Guid todoId) => ...

EOE025: Ambiguous Parameter Binding

// ❌ Wrong - complex type on GET without explicit binding
[Get("/todos")]
public static ErrorOr<List<Todo>> Search(SearchFilter filter) => ...

// ✅ Option 1: Explicit FromQuery
[Get("/todos")]
public static ErrorOr<List<Todo>> Search([FromQuery] SearchFilter filter) => ...

// ✅ Option 2: AsParameters
[Get("/todos")]
public static ErrorOr<List<Todo>> Search([AsParameters] SearchFilter filter) => ...

// ✅ Option 3: FromBody (if intentional)
[Get("/todos")]
public static ErrorOr<List<Todo>> Search([FromBody] SearchFilter filter) => ...

EOE040: Missing CamelCase Policy

// ❌ Wrong - no naming policy
[JsonSerializable(typeof(Todo))]
internal partial class AppJsonContext : JsonSerializerContext { }

// ✅ Correct
[JsonSourceGenerationOptions(
    PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(Todo))]
internal partial class AppJsonContext : JsonSerializerContext { }

EOE050: Version-Neutral with Mappings

// ❌ Wrong - conflicting attributes
[ApiVersionNeutral]
[MapToApiVersion("2.0")]
[Get("/health")]
public static ErrorOr<HealthStatus> Check() => ...

// ✅ Correct - use one or the other
[ApiVersionNeutral]
[Get("/health")]
public static ErrorOr<HealthStatus> Check() => ...

EOE051: Mapped Version Not Declared

// ❌ Wrong - 2.0 not in declared versions
[ApiVersion("1.0")]
public static class UsersEndpoints
{
    [MapToApiVersion("2.0")]  // EOE051
    [Get("/users")]
    public static ErrorOr<List<User>> GetAll() => ...
}

// ✅ Correct - declare all versions
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public static class UsersEndpoints { ... }

EOE054: Invalid API Version Format

// ❌ Wrong - invalid formats
[ApiVersion("v1")]        // No "v" prefix allowed
[ApiVersion("1.0.0.0")]   // Too many segments

// ✅ Correct - valid formats
[ApiVersion("1.0")]
[ApiVersion("2")]
[ApiVersion("1.0-beta")]

EOE041: Missing JsonSerializerContext for AOT

// ❌ Error - [FromBody] without JsonSerializerContext for AOT
[Post("/todos")]
public static ErrorOr<Todo> Create([FromBody] CreateTodoRequest req) => ...

// ✅ Correct - register a JsonSerializerContext
// 1. Create your context
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(CreateTodoRequest))]
[JsonSerializable(typeof(Todo))]
[JsonSerializable(typeof(ProblemDetails))]
internal partial class AppJsonContext : JsonSerializerContext { }

// 2. Register in Program.cs
builder.Services.AddErrorOrEndpoints()
    .UseJsonContext<AppJsonContext>();

EOE055: Duplicate Route Parameter Binding

// ❌ Warning - duplicate binding to same route parameter
[Get("/files/{id}")]
public static ErrorOr<File> Get(
    [FromRoute(Name = "id")] Guid fileId,     // Used
    [FromRoute(Name = "id")] string category) // EOE055: Ignored
{
    return new File(fileId, category);
}

// ✅ Correct - use unique route parameter names
[Get("/files/{fileId}/{category}")]
public static ErrorOr<File> Get(Guid fileId, string category) => ...