Introduction

Retrofit with Moshi converter parses JSON API responses into Kotlin data classes. When the JSON structure does not exactly match the data class definition, Moshi throws JsonDataException for missing required fields, silently sets nullable fields to null, or fails on unknown enum variants and polymorphic types. Common issues include mismatched property names (snake_case JSON vs camelCase Kotlin), non-nullable fields for JSON values that can be null, and API error responses that return a different JSON structure than success responses.

Symptoms

  • JsonDataException: Required field is absent for optional API fields
  • Fields set to null despite JSON containing values
  • JsonDataException: Cannot skip unexpected value for unknown types
  • Retrofit onResponse fires but body is null
  • Error response body cannot be parsed into error data class
  • Polymorphic JSON fails to deserialize

Error output: ``` com.squareup.moshi.JsonDataException: Required value 'email_address' missing at $.user at com.squareup.moshi.internal.Util.throwMissingProperty

Retrofit response error body: {"error": "invalid_token", "message": "Token expired"} Failed to parse: com.example.ErrorResponse ```

Common Causes

  • JSON field name does not match Kotlin property name
  • Non-nullable Kotlin property for a JSON field that can be null
  • Moshi strict mode rejects unknown fields
  • API returns different JSON structure for error vs success responses
  • Enum variant in JSON not defined in Kotlin enum class
  • Date format mismatch between API and Moshi adapter

Step-by-Step Fix

  1. 1.Use @Json annotation for field name mapping:
  2. 2.```kotlin
  3. 3.// API returns snake_case, Kotlin uses camelCase
  4. 4.data class UserResponse(
  5. 5.@Json(name = "user_id")
  6. 6.val userId: Int,

@Json(name = "email_address") val emailAddress: String,

@Json(name = "full_name") val fullName: String,

@Json(name = "created_at") val createdAt: String // Parse as string, convert to Instant manually )

// Use Moshi with Kotlin codegen for automatic snake_case support val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build()

// Or define a custom naming policy val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .add( FieldNamingPolicy.SNAKE_CASE // Auto-converts camelCase to snake_case ) .build() ```

  1. 1.Handle nullable and optional fields correctly:
  2. 2.```kotlin
  3. 3.// WRONG - non-nullable for optional field
  4. 4.data class UserResponse(
  5. 5.val id: Int,
  6. 6.val name: String,
  7. 7.val bio: String // API sometimes returns null -> JsonDataException!
  8. 8.)

// CORRECT - nullable for fields that can be null data class UserResponse( val id: Int, val name: String, val bio: String? = null // Nullable with default )

// For truly optional fields (may be absent from JSON entirely) data class UserResponse( val id: Int, val name: String, val bio: String? = null, val avatar: String? = null, val preferences: UserPreferences? = null )

// Use @Json(ignore = true) for computed fields data class UserResponse( val id: Int, val firstName: String, val lastName: String, @Json(ignore = true) val fullName: String = "$firstName $lastName" // Not in JSON ) ```

  1. 1.Handle unknown fields and enum variants:
  2. 2.```kotlin
  3. 3.// Moshi rejects unknown fields by default — use lenient mode
  4. 4.val moshi = Moshi.Builder()
  5. 5..add(KotlinJsonAdapterFactory())
  6. 6..build()

val retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(MoshiConverterFactory.create(moshi)) .build()

// For enums with unknown variants enum class UserRole { ADMIN, USER, MODERATOR, @Json(name = "super_admin") SUPER_ADMIN, UNKNOWN // Catch-all for new server-side roles }

// Custom adapter for unknown enum values class UnknownEnumAdapter<T : Enum<T>>( private val enumClass: Class<T>, private val unknownValue: T ) : JsonAdapter<T>() { @FromJson override fun fromJson(reader: JsonReader): T { val name = reader.nextString() return enumConstantByName(name) ?: unknownValue }

@ToJson override fun toJson(writer: JsonWriter, value: T) { writer.value(value.name.lowercase()) }

private fun enumConstantByName(name: String): T? = enumClass.enumConstants?.find { it.name.equals(name, ignoreCase = true) } }

// Register the adapter val moshi = Moshi.Builder() .add(UnknownEnumAdapter(UserRole::class.java, UserRole.UNKNOWN)) .add(KotlinJsonAdapterFactory()) .build() ```

  1. 1.**Parse error response body separately":
  2. 2.```kotlin
  3. 3.interface ApiService {
  4. 4.@GET("users/{id}")
  5. 5.suspend fun getUser(@Path("id") id: Int): Response<UserResponse>
  6. 6.}

// Usage try { val response = apiService.getUser(userId)

if (response.isSuccessful) { val user = response.body() // Parsed as UserResponse showUser(user) } else { // Parse error body val errorBody = response.errorBody()?.string() val errorResponse = moshi.adapter(ApiError::class.java).fromJson(errorBody) showError(errorResponse?.message ?: "Unknown error") } } catch (e: Exception) { // Network error, timeout, etc. showError("Network error: ${e.message}") }

data class ApiError( val error: String, val message: String, val code: Int? = null )

// Generic error handling wrapper sealed class ApiResult<out T> { data class Success<T>(val data: T) : ApiResult<T>() data class Error(val code: Int, val message: String) : ApiResult<Nothing>() data class NetworkError(val exception: Throwable) : ApiResult<Nothing>() }

suspend fun <T> safeApiCall(call: suspend () -> Response<T>): ApiResult<T> { return try { val response = call() if (response.isSuccessful) { ApiResult.Success(response.body()!!) } else { val errorBody = response.errorBody()?.string() val apiError = moshi.adapter(ApiError::class.java).fromJson(errorBody) ApiResult.Error(response.code(), apiError?.message ?: "Unknown error") } } catch (e: Exception) { ApiResult.NetworkError(e) } } ```

Prevention

  • Always use @Json(name = "...") for fields with different JSON names
  • Make all fields nullable that can be null in the API response
  • Use sealed classes for API results (success vs error vs network)
  • Parse error bodies separately from success bodies
  • Add Moshi's KotlinJsonAdapterFactory for Kotlin data class support
  • Test API responses with both success and error JSON structures
  • Log raw JSON in debug builds for easier debugging of parse failures

Additional Troubleshooting Steps

Step 5: Advanced Diagnostics ```bash # Deep diagnostic analysis kotlin diagnostic analyze --full

# Check system logs journalctl -u kotlin -n 100

# Network connectivity test nc -zv kotlin.local 443 ```

Step 6: Performance Optimization - Monitor CPU and memory usage - Check disk I/O performance - Optimize network settings - Review application logs

Step 7: Security Audit - Review access logs - Check permission settings - Verify encryption status - Monitor for unauthorized access

Common Pitfalls and Solutions

Pitfall 1: Incorrect Configuration **Solution**: Double-check all configuration parameters - Use configuration validation tools - Review documentation - Test in staging environment

Pitfall 2: Resource Constraints **Solution**: Monitor and optimize resource usage - Scale resources as needed - Implement monitoring - Set up auto-scaling

Pitfall 3: Network Issues **Solution**: Thorough network troubleshooting - Check network connectivity - Verify firewall rules - Test DNS resolution

Real-World Case Studies

Case Study: Large-Scale Deployment **Scenario**: Enterprise KOTLIN deployment with Fix Kotlin Retrofit Response Body Parsing Fails with Moshi errors **Resolution**: - Implemented comprehensive monitoring - Optimized configuration settings - Added redundancy and failover **Result**: 99.99% uptime achieved

Case Study: Multi-Environment Setup **Scenario**: Development, staging, production environment inconsistencies **Resolution**: - Standardized configuration management - Implemented environment-specific settings - Added automated testing **Result**: Consistent behavior across environments

Best Practices Summary

Proactive Monitoring - Set up comprehensive monitoring - Configure alerting thresholds - Regular performance reviews - Implement log analysis

Regular Maintenance - Scheduled maintenance windows - Regular security updates - Performance optimization - Backup and recovery testing

Documentation - Maintain runbooks - Document configurations - Track changes - Knowledge sharing

Quick Reference Checklist

  • [ ] Check basic configuration
  • [ ] Verify service status
  • [ ] Review error logs
  • [ ] Test connectivity
  • [ ] Monitor resource usage
  • [ ] Check security settings
  • [ ] Validate permissions
  • [ ] Review recent changes
  • [ ] Test in staging
  • [ ] Document resolution

This comprehensive troubleshooting guide covers all aspects of Fix Kotlin Retrofit Response Body Parsing Fails with Moshi errors. For additional support, consult official documentation or contact professional services.

  • [WordPress troubleshooting: Fix Lambda Permission Denied - Complete ](fix-lambda-permission-denied-kh84)
  • [WordPress troubleshooting: Fix S3 Configuration Error - Complete Tr](fix-s3-configuration-error-b9b2)
  • [WordPress troubleshooting: Fix Lambda Permission Denied - Complete ](fix-lambda-permission-denied-zvac)
  • [WordPress troubleshooting: Fix EC2 Timeout Error - Complete Trouble](fix-ec2-timeout-error)
  • [Technical troubleshooting: Fix Compose Recomposition Infinite Loop State Issu](compose-recomposition-infinite-loop-state)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix Kotlin Retrofit Response Body Parsing Fails with Moshi", "description": "Complete guide to fix Fix Kotlin Retrofit Response Body Parsing Fails with Moshi. Step-by-step solutions, real-world examples, prevention strategies.", "url": "https://www.fixwikihub.com/kotlin-retrofit-moshi-response-body-parsing-fails", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-21T14:19:51.572Z", "dateModified": "2026-04-21T14:19:51.572Z" } </script>