Skip to content

Fix KotlinReflectPropertyAccessStrategy to yield instead of throwing NPE - #4995

Draft
MateuszNaKodach wants to merge 1 commit into
mainfrom
bug/kotlin-property-access-value-class-id
Draft

Fix KotlinReflectPropertyAccessStrategy to yield instead of throwing NPE#4995
MateuszNaKodach wants to merge 1 commit into
mainfrom
bug/kotlin-property-access-value-class-id

Conversation

@MateuszNaKodach

@MateuszNaKodach MateuszNaKodach commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

WORK IN PROGRESS....

Summary

KotlinReflectPropertyAccessStrategy registers with priority 1000, so PropertyAccessStrategy consults it first for every class. Its propertyFor used kProperty(...)!!, which throws NullPointerException when the target is not a Kotlin class, or when the name does not match exactly one member property.

PropertyAccessStrategy.getProperty walks the registered strategies by priority and moves on when one returns null, which is the documented contract of propertyFor:

while (property == null && strategies.hasNext()) {
    property = strategies.next().propertyFor(targetClass, propertyName);
}

Because this strategy is consulted first, that NPE broke resolution for every consumer instead of letting a lower-priority strategy handle it. propertyFor now returns null in those cases so the chain falls through.

To let the Kotlin override return null, the abstract PropertyAccessStrategy.propertyFor is annotated @Nullable, making the existing "or null if the property could not be found" contract explicit.

Tests

  • A non-Kotlin class (RuntimeException) falls through so a lower-priority strategy resolves message.
  • An unknown property on a Kotlin class resolves to null.

All extension module tests and the common property tests pass.

@MateuszNaKodach
MateuszNaKodach requested a review from a team as a code owner September 1, 2026 09:39
@MateuszNaKodach
MateuszNaKodach requested review from hjohn, jangalinski and zambrovski and removed request for a team September 1, 2026 09:39
@MateuszNaKodach
MateuszNaKodach force-pushed the bug/kotlin-property-access-value-class-id branch from 2c0563d to 7496cb0 Compare September 1, 2026 09:42
return constructor.call(value) as V
// Unbox value classes to their underlying JVM representation, consistent with the default
// field/getter strategies and the type the framework resolves ids and @EventTag values against.
if (value != null && returnClass?.isValue == true) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one

@zambrovski

Copy link
Copy Markdown
Contributor

Just curious, do we also need one for conversion of Kotlin Types to Java Types? Like Int / Integer, etc...

@MateuszNaKodach
MateuszNaKodach force-pushed the bug/kotlin-property-access-value-class-id branch from 7496cb0 to 2d0af57 Compare September 1, 2026 10:05
KotlinReflectPropertyAccessStrategy registers with priority 1000, so
PropertyAccessStrategy consults it first for every class. Its propertyFor used
kProperty(...)!!, which throws NullPointerException when the target is not a
Kotlin class, or when the name does not match exactly one member property.

PropertyAccessStrategy.getProperty walks the registered strategies by priority
and moves on when one returns null, which is the documented contract of
propertyFor. Because this strategy is consulted first, that NPE broke resolution
for every consumer instead of letting a lower-priority strategy handle it.
propertyFor now returns null in those cases.

To let the Kotlin override return null, the abstract
PropertyAccessStrategy.propertyFor is annotated @nullable, making the existing
"or null if the property could not be found" contract explicit.

Adds tests: a non-Kotlin class falls through to another strategy, and an unknown
property resolves to null.
@MateuszNaKodach
MateuszNaKodach force-pushed the bug/kotlin-property-access-value-class-id branch from 2d0af57 to fcd62f6 Compare September 1, 2026 10:35
@MateuszNaKodach MateuszNaKodach changed the title Fix KotlinReflectPropertyAccessStrategy value-class unboxing and null fall-through Fix KotlinReflectPropertyAccessStrategy to yield instead of throwing NPE Sep 1, 2026
@MateuszNaKodach
MateuszNaKodach marked this pull request as draft September 1, 2026 10:41
@smcvb smcvb added this to the Release 5.4.0 milestone Sep 1, 2026
@smcvb smcvb added Type: Bug Use to signal issues that describe a bug within the system. Priority 1: Must Highest priority. A release cannot be made if this issue isn’t resolved. labels Sep 1, 2026
@smcvb smcvb added Priority 2: Should High priority. Ideally, these issues are part of the release they’re assigned to. and removed Priority 1: Must Highest priority. A release cannot be made if this issue isn’t resolved. labels Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Priority 2: Should High priority. Ideally, these issues are part of the release they’re assigned to. Type: Bug Use to signal issues that describe a bug within the system.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants