Skip to content

About

A small Kotlin/JVM library that normalizes Django REST Framework error responses into a simple list of field and global errors.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

DRF Error Handler

A small Kotlin/JVM library that normalizes Django REST Framework error responses into a simple list of field and global errors.

CI License: MIT

DRF can return validation errors in several shapes depending on whether the response came from a serializer, nested serializer, list serializer, permission check, authentication failure, or generic API exception. That flexibility is useful on the server, but it creates repetitive parsing code in Android, desktop, CLI, or other Kotlin clients.

DRF Error Handler exists to make that client code predictable:

DRFErrorResponse(
    errors = listOf(
        DRFError(field = "email", message = "Enter a valid email address.")
    )
)

Features

  • Parses field validation errors.
  • Parses nested serializer errors into dot paths such as author.email.
  • Parses list serializer errors into indexed paths such as items[1].quantity.
  • Treats non_field_errors and detail responses as global errors.
  • Handles leaked Python ErrorDetail("...", code="...") values in JSON-like payloads.
  • Summarizes Django/DRF HTML error pages, including debug 404/500 responses.
  • Returns a fallback global error for malformed or unexpected payloads instead of throwing.
  • Has no dependency on Android UI frameworks or HTTP clients.

Installation

Add the dependency from Maven Central:

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.kallyas:drferrorhandler:0.1.1")
}

For local development, publish it to your local Maven repository:

./gradlew publishToMavenLocal

Quick Start

import com.github.kallyas.DRFErrorHandler

val response = DRFErrorHandler.parse(
    """
    {
        "email": ["Enter a valid email address."],
        "password": ["This field is required."]
    }
    """.trimIndent()
)

response.errors.forEach { error ->
    println("${error.field}: ${error.message}")
}

Output:

email: Enter a valid email address.
password: This field is required.

Examples

Generic API Error

DRF exception responses usually use a top-level detail key:

val response = DRFErrorHandler.parse(
    """{"detail": "Authentication credentials were not provided."}"""
)

val message = response.globalErrors.firstOrNull()?.message

Nested Serializer Error

Nested objects are flattened into field paths:

val response = DRFErrorHandler.parse(
    """
    {
        "author": {
            "email": ["Enter a valid email address."]
        }
    }
    """.trimIndent()
)

val emailErrors = response.getErrorsForField("author.email")

List Serializer Error

List indexes are preserved:

val response = DRFErrorHandler.parse(
    """
    [
        {},
        {"title": ["This field is required."]}
    ]
    """.trimIndent()
)

val titleErrors = response.getErrorsForField("[1].title")

Android Form Error Mapping

val parsed = DRFErrorHandler.parse(errorBody)

emailInput.error = parsed.getErrorsForField("email").firstOrNull()?.message
passwordInput.error = parsed.getErrorsForField("password").firstOrNull()?.message

parsed.globalErrors.firstOrNull()?.let { error ->
    showSnackbar(error.message)
}

Django Debug HTML Error

When Django returns an HTML debug page for a 404 or 500 response, the parser returns a concise global error instead of the full HTML document:

val response = DRFErrorHandler.parse(htmlErrorBody)

val message = response.globalErrors.firstOrNull()?.message
// Example: "OperationalError at /api/orders/"

API

DRFErrorHandler.parse(jsonString: String): DRFErrorResponse

Parses a raw DRF error response string and returns a normalized response.

The method is safe to call from networking error paths. It does not throw for malformed input; instead, it returns one global error containing the original payload, or "An unknown error occurred." for blank input.

DRFError

data class DRFError(
    val field: String?,
    val message: String
)

field is null for global errors, non_field_errors, and generic detail responses.

DRFErrorResponse

data class DRFErrorResponse(
    val errors: List<DRFError>
) {
    val hasErrors: Boolean
    fun getErrorsForField(field: String): List<DRFError>
    val globalErrors: List<DRFError>
}

Use Cases

  • Attach DRF validation messages to Android form fields.
  • Display global API failures from authentication, permission, throttling, or server errors.
  • Normalize nested serializer errors before rendering them in a client app.
  • Send consistent error paths to logs, crash reports, or analytics.
  • Reuse one parser across JVM, Android, CLI, and desktop Kotlin code.

Limitations

  • This library only parses and normalizes errors. It does not make HTTP requests.
  • Field matching is exact. For example, items[0].name and items.name are different paths.
  • Error messages are returned as provided by the backend. Handle localization on the server or in the calling app.
  • HTML error pages are summarized from the <title> tag when available, or from stripped body text otherwise.
  • ErrorDetail(...) support is a compatibility fallback for malformed payloads. Prefer valid JSON responses from your API.

Development

Run tests:

./gradlew test

Publish to the local Maven repository:

./gradlew publishToMavenLocal

About

A small Kotlin/JVM library that normalizes Django REST Framework error responses into a simple list of field and global errors.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages