From ABP Sensei
Handles ABP Framework exceptions: BusinessException, UserFriendlyException, RemoteServiceErrorResponse, HTTP status mapping, and error code localization.
How this skill is triggered — by the user, by Claude, or both
Slash command
/abp-sensei:abp-exception-handlingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
User asks about exception handling, error handling, RemoteServiceErrorResponse, error codes, business exceptions, HTTP status mapping, self-logging exceptions, or API error responses in ABP Framework.
User asks about exception handling, error handling, RemoteServiceErrorResponse, error codes, business exceptions, HTTP status mapping, self-logging exceptions, or API error responses in ABP Framework.
ABP provides a built-in exception handling infrastructure that:
All API errors return a RemoteServiceErrorResponse JSON:
{
"error": {
"message": "This topic is locked and can not add a new message"
}
}
{
"error": {
"code": "App:010046",
"message": "An error occurred while processing your request."
}
}
Implement IHasErrorCode to include error codes:
public class MyBusinessException : Exception, IHasErrorCode
{
public string Code => "App:010046";
}
{
"error": {
"code": "App:010046",
"message": "Something went wrong.",
"details": "Stack trace or additional context..."
}
}
Implement IHasErrorDetails to include details:
public class MyException : Exception, IHasErrorDetails
{
public string Details => "Additional diagnostic information...";
}
{
"error": {
"code": "App:010046",
"message": "Your request is not valid, please correct and try again!",
"validationErrors": [
{
"message": "Username should be minimum length of 3.",
"members": ["userName"]
},
{
"message": "Password is required",
"members": ["password"]
}
]
}
}
AbpValidationException implements IHasValidationErrors and is auto-thrown on invalid input.
public class BookNotFoundException : Exception
{
public Guid BookId { get; }
public BookNotFoundException(Guid bookId)
: base($"Book not found with id: {bookId}")
{
BookId = bookId;
}
}
public class InsufficientStockException : Exception, IHasErrorCode
{
public string Code => "BookStore:010001";
public InsufficientStockException(string message) : base(message) { }
}
public class UserFriendlyException : Exception
{
public UserFriendlyException(
string message,
string details = null,
string code = null
) : base(message) { }
}
Use localization resource:
throw new UserFriendlyException(
L["ErrorMessage:InsufficientStock"]
);
ABP automatically maps exceptions to HTTP status codes:
| Exception Type | HTTP Status |
|---|---|
AbpValidationException | 400 Bad Request |
AbpAuthorizationException | 403 Forbidden |
EntityNotFoundException | 404 Not Found |
UserFriendlyException | 400 Bad Request |
EntityAlreadyExistsException | 409 Conflict |
NonImplementException | 501 Not Implemented |
Generic Exception | 500 Internal Server Error |
Configure<AbpExceptionHandlingOptions>(options =>
{
options.MapToStatusCode<MyCustomException>(StatusCodes.Status409Conflict);
});
Caught exceptions are automatically logged by ABP.
Implement IHasLogLevel to control the log level:
public class MyExpectedException : Exception, IHasLogLevel
{
public LogLevel LogLevel => LogLevel.Warning;
public MyExpectedException(string message) : base(message) { }
}
Default log levels:
AbpValidationException → WarningAbpAuthorizationException → WarningUserFriendlyException → WarningException → ErrorExceptions can write additional logs by implementing IExceptionWithSelfLogging:
public class MyException : Exception, IExceptionWithSelfLogging
{
public void Log(ILogger logger)
{
logger.LogWarning("Additional context: {ContextData}", SomeData);
}
}
Use ILogger.LogException extension method for manual logging:
logger.LogException(myException);
Configure<AbpExceptionHandlingOptions>(options =>
{
// Send exception details to client (development only!)
options.SendExceptionsDetailsToClients = true;
// Include stack trace in response (development only!)
options.IncludeStackTraceInExceptionDetails = true;
// Custom exception mappers
options.MapToStatusCode<MyException>(StatusCodes.Status409Conflict);
});
Warning: Never enable
SendExceptionsDetailsToClientsorIncludeStackTraceInExceptionDetailsin production — they expose internal implementation details.
UserFriendlyException for errors that should be shown directly to usersIHasErrorCode for machine-readable error codes (client-side handling)IHasLogLevel to control noise in logs (expected errors = Warning)IExceptionWithSelfLogging for exceptions that need additional context loggedAbpExceptionHandlingOptionsException)EntityNotFoundException for missing entities (auto-mapped to 404)public class BookAppService : ApplicationService
{
public async Task<BookDto> GetAsync(Guid id)
{
var book = await _bookRepository.FindAsync(id);
if (book == null)
{
throw new EntityNotFoundException(typeof(Book), id);
}
return ObjectMapper.Map<Book, BookDto>(book);
}
}
public class InsufficientStockException : Exception, IHasErrorCode
{
public string Code => "BookStore:010001";
public int RequestedQuantity { get; }
public int AvailableQuantity { get; }
public InsufficientStockException(int requested, int available)
: base($"Requested {requested} but only {available} available")
{
RequestedQuantity = requested;
AvailableQuantity = available;
}
}
try {
await bookService.create(input);
} catch (error) {
if (error.response?.data?.error?.code === 'BookStore:010001') {
// Handle insufficient stock
showStockWarning(error.response.data.error.validationErrors);
}
}
Request arrives
↓
ABP handles request
↓
Exception thrown
↓
ABP Exception Handler intercepts
↓
Determines HTTP status code
↓
Logs exception (respects IHasLogLevel)
↓
Calls IExceptionWithSelfLogging.Log() if implemented
↓
Builds RemoteServiceErrorResponse
↓
Returns HTTP response with error JSON
npx claudepluginhub burakdmir/abp-skills --plugin abp-senseiProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.