{"record":{"id":"b09d12aaedbc392e","repo":"apache/druid","slug":"encountered-metric-with-null-or-empty-name-at-posi","errorCode":null,"errorMessage":"Encountered metric with null or empty name at position %d","messagePattern":"Encountered metric with null or empty name at position (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/segment/indexing/DataSchema.java","lineNumber":553,"sourceCode":"                    field,\n                    dimSchema.getColumnType()\n                );\n          } else if (!sawTimeDimension) {\n            // Skip adding __time to \"fields\" (once) if it's listed as a dimension, so it doesn't show up as an error.\n            sawTimeDimension = true;\n            continue;\n          }\n        }\n\n        fields.computeIfAbsent(field, k -> TreeMultiset.create()).add(\"dimensions list\");\n      }\n    }\n\n    if (aggregators != null) {\n      for (int i = 0; i < aggregators.length; i++) {\n        final String field = aggregators[i].getName();\n        if (Strings.isNullOrEmpty(field)) {\n          throw new IAE(\"Encountered metric with null or empty name at position %d\", i);\n        }\n\n        fields.computeIfAbsent(field, k -> TreeMultiset.create()).add(\"metricsSpec list\");\n      }\n    }\n\n    return getFieldsOrThrowIfErrors(fields);\n  }\n\n  /**\n   * Validates that each {@link AggregateProjectionSpec} does not have duplicate column names in\n   * {@link AggregateProjectionSpec#groupingColumns} and {@link AggregateProjectionSpec#aggregators} and that segment\n   * {@link Granularity} is at least as coarse as {@link AggregateProjectionSchema#effectiveGranularity}\n   */\n  public static void validateProjections(\n      @Nullable List<AggregateProjectionSpec> projections,\n      @Nullable Granularity segmentGranularity\n  )","sourceCodeStart":535,"sourceCodeEnd":571,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/segment/indexing/DataSchema.java#L535-L571","documentation":"During DataSchema construction, output field names for aggregators are computed and validated. Every aggregator must have a non-null, non-empty name because metric names become column identifiers; a blank name cannot be indexed, so this IAE pinpoints the offending position.","triggerScenarios":"Building a DataSchema whose metricsSpec contains an aggregator (e.g. count, doubleSum, longSum) with name omitted, null, or \"\", or with a post-aggregator referencing an unnamed aggregator.","commonSituations":"Hand-written or templated ingestion specs where the \"name\" key was deleted, JSON with a typo like \"nane\", or programmatic spec builders not setting the aggregator name.","solutions":["Add a unique, non-empty \"name\" to every aggregator in metricsSpec.","Check aggregator factories created programmatically call setName(...) with a real value.","Validate the spec JSON (names non-empty) before submitting the ingestion task."],"exampleFix":"// before\n{ \"type\": \"count\", \"name\": null }\n// after\n{ \"type\": \"count\", \"name\": \"rowCount\" }","handlingStrategy":"validation","validationCode":"for (AggregatorFactory agg : dataSchema.getAggregators()) {\n  if (agg == null || agg.getName() == null || agg.getName().isEmpty()) {\n    throw new IllegalArgumentException(\"Every aggregator must have a non-empty name\");\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set explicit, unique metric names in metricsSpec.","Lint ingestion specs for required aggregator fields before submission."],"tags":["ingestion-spec","validation","metrics"],"backgroundTag":"empty-required-field","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}