quarkusio/quarkus · error · ReflectiveOperationException

No no-arg constructor found on $strategy

Error message

No no-arg constructor found on $strategy

What it means

JsonProducer.loadStrategyClass loads a custom JsonNamingStrategy by class name from the thread context classloader and instantiates it via a zero-argument constructor. If the class has no no-arg constructor, a ReflectiveOperationException is thrown and rethrown as IllegalArgumentException("Error loading naming strategy: ..."), aborting Json production.

Source

Thrown at extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/kotlin/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonProducer.kt:84

        strategyProperty.set(
            jsonBuilder,
            if (strategy.startsWith("JsonNamingStrategy")) {
                jsonProducer.extractBuiltIn(strategy)
            } else {
                jsonProducer.loadStrategyClass(strategy)
            },
        )
    }

    @ExperimentalSerializationApi
    private fun loadStrategyClass(strategy: String): JsonNamingStrategy {
        try {
            val strategyClass: Class<JsonNamingStrategy> =
                Thread.currentThread().contextClassLoader.loadClass(strategy)
                    as Class<JsonNamingStrategy>
            val constructor =
                strategyClass.constructors.find { it.parameterCount == 0 }
                    ?: throw ReflectiveOperationException(
                        "No no-arg constructor found on $strategy"
                    )
            return constructor.newInstance() as JsonNamingStrategy
        } catch (e: ReflectiveOperationException) {
            throw IllegalArgumentException(
                "Error loading naming strategy:  ${strategy.substringAfter('.')}",
                e,
            )
        }
    }

    @ExperimentalSerializationApi
    private fun extractBuiltIn(strategy: String): JsonNamingStrategy {
        val kClass = Builtins::class
        val property =
            kClass.memberProperties.find { property ->
                property.name == strategy.substringAfter('.')
            }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Provide a no-arg constructor on the custom JsonNamingStrategy class (default Kotlin object or class with default constructor)
  2. Register strategy dependencies statically or via companion object defaults instead of constructor parameters
  3. Use a built-in strategy (JsonNamingStrategy.SnakeCase, KebabCase, etc.) if a custom one is unnecessary
  4. Verify the configured class name resolves to the intended strategy class

Example fix

// before
class SnakeCasePlus(val prefix: String) : JsonNamingStrategy { ... }
// after
class SnakeCasePlus : JsonNamingStrategy {
    private val delegate = JsonNamingStrategy.SnakeCase
    override fun propertyName(name: String, serialName: String?) = "my_prefix_" + delegate.propertyName(name, serialName)
}
Defensive patterns

Strategy: validation

Validate before calling

// Verify strategy class has a no-arg constructor before configuring
val clazz = Thread.currentThread().contextClassLoader.loadClass(strategyClassName)
require(clazz.constructors.any { it.parameterCount == 0 }) {
    "$strategyClassName must provide a no-arg constructor"
}

Type guard

fun <T> Class<T>.hasNoArgConstructor(): Boolean = constructors.any { it.parameterCount == 0 }

Try / catch

try {
    val strategy = loadNamingStrategy(strategyClassName)
} catch (e: IllegalArgumentException) {
    if (e.message?.startsWith("Error loading naming strategy") == true) {
        strategy = JsonNamingStrategy.Default
    } else throw e
}

Prevention

When it happens

Trigger: Configuring quarkus.kotlin-serialization.json.naming-strategy with a custom strategy class that only defines parameterized constructors.

Common situations: Custom naming strategies with constructor dependencies; typo'd FQCN resolving to the wrong class; strategies requiring DI that cannot be reflectively instantiated.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/ed7884d0dca4d526. Report an issue: GitHub.