apache/druid · error · IllegalStateException
Failed to parse metrics and dimensions
Error message
Failed to parse metrics and dimensions
What it means
Opentsdb emitter's EventConverter.readMap deserializes the metrics/dimensions YAML/JSON config file into Map<String, Set<String>>. If the stream cannot be parsed as that structure (malformed YAML, wrong shape), it throws ISE with 'Failed to parse metrics and dimensions'.
Source
Thrown at extensions-contrib/opentsdb-emitter/src/main/java/org/apache/druid/emitter/opentsdb/EventConverter.java:123
}
private Map<String, Set<String>> readMap(ObjectMapper mapper, String metricMapPath)
{
try {
InputStream is;
if (Strings.isNullOrEmpty(metricMapPath)) {
log.info("Using default metric map");
is = this.getClass().getClassLoader().getResourceAsStream("defaultMetrics.json");
} else {
log.info("Using default metric map located at [%s]", metricMapPath);
is = new FileInputStream(new File(metricMapPath));
}
return mapper.readerFor(new TypeReference<Map<String, Set<String>>>()
{
}).readValue(is);
}
catch (IOException e) {
throw new ISE(e, "Failed to parse metrics and dimensions");
}
}
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Validate the metrics/dimensions file is well-formed YAML/JSON and a map of metric-name -> list of strings
- Fix indentation and ensure values are lists, e.g. `my.metric: [host, service]`
- Load the file through a YAML linter/parser locally before deploying
Example fix
// before (bad YAML)
metrics:
requests: host, service
// after
metrics:
requests:
- host
- service Defensive patterns
Strategy: validation
Validate before calling
Map<String, Set<String>> parsed = new Yaml().load(configFile);
if (parsed == null || parsed.isEmpty()) throw new IllegalArgumentException("opentsdb metrics config must be a non-empty map");
parsed.values().forEach(v -> { if (!(v instanceof Set || v instanceof List)) throw new IllegalArgumentException("values must be lists of dimensions"); }); Try / catch
try { new OpentsdbEmitter(config, mapper); } catch (IllegalStateException e) { if (e.getMessage().contains("parse metrics")) { validateConfigFile(path); } } Prevention
- Run YAML linting on the opentsdb metrics config in CI
- Keep values as YAML lists, never comma-separated strings
- Validate the file against the Map<String, Set<String>> schema after edits
When it happens
Trigger: The opentsdb emitter's metric/dimension definition file contains invalid YAML/JSON, or its top-level structure is not an object mapping metric names to arrays/sets of strings; read during emitter construction.
Common situations: Hand-edited metrics config with indentation errors, using a list at top level instead of a map, or values written as comma-separated strings instead of lists.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Emit called unexpectedly before service start
- Failed to parse metric configuration
- Cannot deserialize type[%s] to an RoaringBitmap64Counter:
- Can't load TrustStore. Truststore path or password is not se
- Unable to load TrustStore
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/16f0f6c330f5b540.
Report an issue: GitHub.