{"record":{"id":"ed7884d0dca4d526","repo":"quarkusio/quarkus","slug":"no-no-arg-constructor-found-on-strategy","errorCode":null,"errorMessage":"No no-arg constructor found on $strategy","messagePattern":"No no-arg constructor found on \\$strategy","errorType":"exception","errorClass":"ReflectiveOperationException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/kotlin/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonProducer.kt","lineNumber":84,"sourceCode":"        strategyProperty.set(\n            jsonBuilder,\n            if (strategy.startsWith(\"JsonNamingStrategy\")) {\n                jsonProducer.extractBuiltIn(strategy)\n            } else {\n                jsonProducer.loadStrategyClass(strategy)\n            },\n        )\n    }\n\n    @ExperimentalSerializationApi\n    private fun loadStrategyClass(strategy: String): JsonNamingStrategy {\n        try {\n            val strategyClass: Class<JsonNamingStrategy> =\n                Thread.currentThread().contextClassLoader.loadClass(strategy)\n                    as Class<JsonNamingStrategy>\n            val constructor =\n                strategyClass.constructors.find { it.parameterCount == 0 }\n                    ?: throw ReflectiveOperationException(\n                        \"No no-arg constructor found on $strategy\"\n                    )\n            return constructor.newInstance() as JsonNamingStrategy\n        } catch (e: ReflectiveOperationException) {\n            throw IllegalArgumentException(\n                \"Error loading naming strategy:  ${strategy.substringAfter('.')}\",\n                e,\n            )\n        }\n    }\n\n    @ExperimentalSerializationApi\n    private fun extractBuiltIn(strategy: String): JsonNamingStrategy {\n        val kClass = Builtins::class\n        val property =\n            kClass.memberProperties.find { property ->\n                property.name == strategy.substringAfter('.')\n            }","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/kotlin/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonProducer.kt#L66-L102","documentation":"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.","triggerScenarios":"Configuring quarkus.kotlin-serialization.json.naming-strategy with a custom strategy class that only defines parameterized constructors.","commonSituations":"Custom naming strategies with constructor dependencies; typo'd FQCN resolving to the wrong class; strategies requiring DI that cannot be reflectively instantiated.","solutions":["Provide a no-arg constructor on the custom JsonNamingStrategy class (default Kotlin object or class with default constructor)","Register strategy dependencies statically or via companion object defaults instead of constructor parameters","Use a built-in strategy (JsonNamingStrategy.SnakeCase, KebabCase, etc.) if a custom one is unnecessary","Verify the configured class name resolves to the intended strategy class"],"exampleFix":"// before\nclass SnakeCasePlus(val prefix: String) : JsonNamingStrategy { ... }\n// after\nclass SnakeCasePlus : JsonNamingStrategy {\n    private val delegate = JsonNamingStrategy.SnakeCase\n    override fun propertyName(name: String, serialName: String?) = \"my_prefix_\" + delegate.propertyName(name, serialName)\n}","handlingStrategy":"validation","validationCode":"// Verify strategy class has a no-arg constructor before configuring\nval clazz = Thread.currentThread().contextClassLoader.loadClass(strategyClassName)\nrequire(clazz.constructors.any { it.parameterCount == 0 }) {\n    \"$strategyClassName must provide a no-arg constructor\"\n}","typeGuard":"fun <T> Class<T>.hasNoArgConstructor(): Boolean = constructors.any { it.parameterCount == 0 }","tryCatchPattern":"try {\n    val strategy = loadNamingStrategy(strategyClassName)\n} catch (e: IllegalArgumentException) {\n    if (e.message?.startsWith(\"Error loading naming strategy\") == true) {\n        strategy = JsonNamingStrategy.Default\n    } else throw e\n}","preventionTips":["Always give custom JsonNamingStrategy classes a no-arg constructor","Prefer Kotlin `object` declarations for stateless strategies","Verify the configured FQCN at startup with a smoke test"],"tags":["kotlin","kotlinx-serialization","reflection","configuration","naming-strategy"],"backgroundTag":"missing-no-arg-constructor","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}