apache / apache/dubbo

[Bug] JavaBeanSerializeUtil.serialize() throws IllegalArgumentException on a Map containing a null key

Open Beginner friendly
#16,432 3 comments 1 reaction 0 assignees View on GitHub
component/need-triage type/need-triage
Dominant language
Java
Stars
41.6k
Forks
26.4k
Avg merge
15h 13m
Merged PRs (30d)
4

Description

### Pre-check

- [x] I am sure that all the content I provide is in English.

### Search before asking

- [x] I had searched in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no similar issues.

### Apache Dubbo Component

Java SDK (apache/dubbo)

### Dubbo Version

dubbo 3.2.20 (tag dubbo-3.2.20)

### Steps to reproduce this issue

JavaBeanSerializeUtil.serialize() fails on a java.util.HashMap that contains a null key. HashMap permits exactly one null key, so this is a legal argument, and the serializer's own code has an explicit branch for it — but the value that branch produces is then rejected by a null check further down the same call chain.

import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
import java.util.HashMap;
import java.util.Map;

public class NullKeyRepro {
public static void main(String[] args) {
Map ok = new HashMap<>();
ok.put("k", "v");
System.out.println("without null key: " + (JavaBeanSerializeUtil.serialize(ok) != null));

Map withNullKey = new HashMap<>();
withNullKey.put(null, "value1"); // HashMap permits one null key
JavaBeanSerializeUtil.serialize(withNullKey); // throws
}
}

### What you expected to happen

The map is serialised, with the null key represented as a null descriptor — which is what the code appears to intend.

### Anything else

### Actual
```
without null key: true
Exception in thread "main" java.lang.IllegalArgumentException: Property name is null
```

### Root cause
`dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java`, lines 162–166:

```java
map.forEach((key, value) -> {
Object keyDescriptor = key == null ? null : createDescriptorIfAbsent(key, accessor, cache);
Object valueDescriptor = value == null ? null : createDescriptorIfAbsent(value, accessor, cache);
descriptor.setProperty(keyDescriptor, valueDescriptor);
});
```

Line 163 deliberately produces `null` for a null key. Line 165 passes it to
`JavaBeanDescriptor.setProperty`, whose first statement (`JavaBeanDescriptor.java`,
lines 118–120) is:

```java
public Object setProperty(Object propertyName, Object propertyValue) {
notNull(propertyName, "Property name is null");
return properties.put(propertyName, propertyValue);
}
```

So the null-producing branch and the null-rejecting guard sit in the same call
chain. Either the ternary on line 163 is dead for keys, or the guard is too strict
for this call site.

### Notes
Not introduced by 3.2.20 — the code path is long-standing. The nearest existing
issue I found, #12248, is a different trigger (a null *parameter* causing an NPE
in generic-call bean mode).

### Do you have a (mini) reproduction demo?

- [ ] Yes, I have a minimal reproduction demo to help resolve this issue more effectively!

### Are you willing to submit a pull request to fix on your own?

- [ ] Yes I am willing to submit a pull request on my own!

### Code of Conduct

- [x] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct)

Contributor guide

Open the contributing guide

Research direction

Start with the null-key reproduction and read JavaBeanSerializeUtil.java around lines 162–166, then follow the call into JavaBeanDescriptor.java around lines 118–120. Determine how the existing null-key branch should interact with the property-name check; done means a HashMap containing one null key serializes without IllegalArgumentException while existing non-null-key behavior remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.