conductor-oss/conductor · error · IllegalArgumentException
cannot map non-scalar map key:
Error message
cannot map non-scalar map key:
What it means
Thrown as IllegalArgumentException by MapType.getProtoType when the map's key type is not a ScalarType. Protobuf map fields only permit scalar keys (integral, bool, string), so a Map<CustomType, V> or Map<List, V> cannot be represented and protogen refuses to emit a proto map for it.
Source
Thrown at annotations-processor/src/main/java/com/netflix/conductor/annotationsprocessor/protogen/types/MapType.java:121
method.endControlFlow();
method.addStatement("to.$L($L)", javaMethodName("set", field), mapName);
}
}
@Override
public TypeName resolveJavaProtoType() {
return ParameterizedTypeName.get(
(ClassName) getRawJavaType(),
getKeyType().getJavaProtoType(),
getValueType().getJavaProtoType());
}
@Override
public String getProtoType() {
AbstractType keyType = getKeyType();
AbstractType valueType = getValueType();
if (!(keyType instanceof ScalarType)) {
throw new IllegalArgumentException(
"cannot map non-scalar map key: " + this.getJavaType());
}
return String.format("map<%s, %s>", keyType.getProtoType(), valueType.getProtoType());
}
}
View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Change the map key to a scalar: Map<String, V>, Map<Integer, V>, Map<Long, V>, or Map<Boolean, V>.
- If a composite key is required, flatten it: convert Map<Composite,V> into a List<CompositeEntry> where CompositeEntry holds the key fields plus the value.
- Register a scalar mapping via TypeMapper.addScalarType only if the key is genuinely a primitive-like type supported by proto.
Example fix
// before
@ProtoMessage public class OrderBook {
Map<Instrument, Integer> quantities; // Instrument is a message
}
// after
@ProtoMessage public class OrderBook {
Map<String, Integer> quantitiesByInstrumentId;
} Defensive patterns
Strategy: validation
Validate before calling
// Static design-time check: map keys must be scalar
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.Map;
static void assertScalarMapKeys(Class<?> msg) {
for (Field f : msg.getDeclaredFields()) {
if (Map.class.isAssignableFrom(f.getType())) {
ParameterizedType pt = (ParameterizedType) f.getGenericType();
Class<?> keyClass = (Class<?>) pt.getActualTypeArguments()[0];
Set<Class<?>> scalars = Set.of(int.class, Integer.class, long.class, Long.class,
String.class, boolean.class, Boolean.class);
if (!scalars.contains(keyClass)) {
throw new IllegalStateException("Map key of " + f + " is non-scalar: " + keyClass);
}
}
}
} Prevention
- Restrict protobuf map keys to integral, bool, or string.
- Add a design-time reflection check over @ProtoMessage fields.
- Flatten composite-key maps into a list of entry messages.
When it happens
Trigger: A @ProtoMessage class has a field of type Map<K,V> where K is a non-scalar Java type (another message, a collection, Object). TypeMapper builds a MapType, and when getProtoType() renders the field it hits the guard.
Common situations: Modeling domain objects with composite keys (e.g., Map<SomeEnum, V> if the enum is not registered as scalar, or Map<MyMessage, V>); introducing a new keyed collection that the codegen does not support.
Related errors
- Cannot map type:
- duplicate type declaration:
- cannot wrap primitive type:
- missing wrapper class:
- missing Jar file
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/eb9ef3f05b5c1b04.
Report an issue: GitHub.