apache/druid · error · ProvisionException
Dot at the end of property: %s
Error message
Dot at the end of property: %s
What it means
hieraricalPutValue builds nested maps from dotted property keys; a key ending with a dot would produce an empty final segment, which cannot map to a config field. Druid throws ProvisionException 'Dot at the end of property' to fail fast on the malformed key.
Source
Thrown at processing/src/main/java/org/apache/druid/guice/JsonConfigurator.java:240
String originalProperty,
String property,
Object value,
Map<String, Object> targetMap
)
{
int dotIndex = property.indexOf('.');
// Always put property with name even if it is of form a.b. This will make sure the property is available for classes
// where JsonProperty names are of the form a.b
// Note:- this will cause more than required properties to be present in the jsonMap.
targetMap.put(property, value);
if (dotIndex < 0) {
return;
}
if (dotIndex == 0) {
throw new ProvisionException(StringUtils.format("Double dot in property: %s", originalProperty));
}
if (dotIndex == property.length() - 1) {
throw new ProvisionException(StringUtils.format("Dot at the end of property: %s", originalProperty));
}
String nestedKey = property.substring(0, dotIndex);
Object nested = targetMap.computeIfAbsent(nestedKey, k -> new HashMap<String, Object>());
if (!(nested instanceof Map)) {
// Clash is possible between properties, which are used to configure different objects: e. g.
// druid.emitter=parametrized is used to configure Emitter class, and druid.emitter.parametrized.xxx=yyy is used
// to configure ParametrizedUriEmitterConfig object. So skipping xxx=yyy key-value pair when configuring Emitter
// doesn't make any difference. That is why we just log this situation, instead of throwing an exception.
log.info(
"Skipping property [%s]: one of it's prefixes [%s] is also used as a property key.",
originalProperty,
propertyPrefix
);
return;
}
Map<String, Object> nestedMap = (Map<String, Object>) nested;
hieraricalPutValue(propertyPrefix, originalProperty, property.substring(dotIndex + 1), value, nestedMap);
}View on GitHub (pinned to 9b90983fd2)
Solutions
- Remove the trailing dot from the listed property key so it ends with an actual key segment
- Delete the whole line if the property is no longer needed
- Regenerate or lint runtime.properties with a validator that rejects keys ending in '.'
Example fix
// before druid.emitter.=parametrized // after druid.emitter=parametrized
Defensive patterns
Strategy: validation
Validate before calling
for (String key : props.stringPropertyNames()) {
if (key.endsWith(".")) throw new IllegalArgumentException("Trailing dot in property key: " + key);
} Try / catch
try { injector = Guice.createInjector(...); } catch (ProvisionException e) { if (e.getMessage().contains("Dot at the end")) log.error("Fix trailing-dot property key"); throw e; } Prevention
- When deleting a leaf config value, delete the whole line rather than leaving 'key.='
- Run a properties lint step before distributing configs to nodes
- Use diff review on runtime.properties changes
When it happens
Trigger: hieraricalPutValue sees dotIndex == property.length() - 1, i.e. the property key string ends in '.' — triggered from configurate or recursively from hieraricalPutValue itself.
Common situations: A runtime.properties line like 'druid.emitter.=parametrized' or 'druid.storage.type.=' left after deleting the leaf key but not the trailing dot, often from manual editing or find/replace.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Double dot in property: %s
- %s - %s
- JsonConfigurator requires default classes to have zero-arg c
- JsonConfigurator requires Jackson-annotated Config objects t
- Some value must be configured for [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/ac33c028026e09ab.
Report an issue: GitHub.