apache/druid · error · IllegalArgumentException

Pod template file not specified for [%s]

Error message

Pod template file not specified for [%s]

What it means

Thrown by DynamicConfigPodTemplateSelector.loadPodTemplate when the property druid.indexer.runner.k8s.podTemplate.<key> exists in the selector's key set (so a template for this key was registered) but its value is null — i.e. no pod template file path was actually specified. The lazy supplier runs when a task first requests the template, surfacing this IllegalArgumentException at task launch time.

Source

Thrown at extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelector.java:102

  {
    Set<String> taskAdapterTemplates = new HashSet<>();

    for (String runtimeProperty : properties.stringPropertyNames()) {
      if (runtimeProperty.startsWith(TASK_PROPERTY)) {
        String[] taskAdapterPropertyPaths = runtimeProperty.split("\\.");
        taskAdapterTemplates.add(taskAdapterPropertyPaths[taskAdapterPropertyPaths.length - 1]);
      }
    }

    return taskAdapterTemplates;
  }

  private PodTemplate loadPodTemplate(String key, Properties properties) throws IAE
  {
    String property = TASK_PROPERTY + key;
    String podTemplateFile = properties.getProperty(property);
    if (podTemplateFile == null) {
      throw new IAE("Pod template file not specified for [%s]", property);
    }

    try {
      // Use Optional to assert unmarshal result is non-null.
      Optional<PodTemplate> maybeTemplate = Optional.of(Serialization.unmarshal(
          Files.newInputStream(new File(podTemplateFile).toPath()),
          PodTemplate.class
      ));

      return maybeTemplate.get();
    }
    catch (Exception e) {
      throw new IAE(e, "Failed to load pod template file for [%s] at [%s]", property, podTemplateFile);
    }
  }

  @SuppressWarnings("ResultOfMethodCallIgnored")
  private void validateTemplateSupplier(Supplier<PodTemplate> templateSupplier) throws IAE

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Set the file path for the missing template key, e.g. druid.indexer.runner.k8s.podTemplate.<key>=/path/to/template.yaml
  2. Confirm the property is present on ALL Overlord instances and not removed by dynamic config updates
  3. Restart/redeploy the Overlord so the selector re-reads a consistent properties set

Example fix

// before
# template key registered but no path
druid.indexer.runner.k8s.podTemplate.batch=

// after
druid.indexer.runner.k8s.podTemplate.batch=/etc/druid/k8s/batch.yaml
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every podTemplate key has a non-empty file path before use
String prop = "druid.indexer.runner.k8s.podTemplate." + key;
String path = props.getProperty(prop);
if (path == null || path.trim().isEmpty()) {
    throw new IllegalArgumentException(prop + " must point to a pod template file");
}

Prevention

When it happens

Trigger: A podTemplate key was discovered in the properties (key present with empty/blank handling differences) but properties.getProperty(TASK_PROPERTY + key) returns null when the supplier executes — e.g. the key was registered from taskAdapterTemplates keys but the file path property was never set, or the property was removed between selector construction and template load.

Common situations: Config hot-reload / dynamic reconfiguration removing the file path while the selector still knows the template name; typos leaving a key entry without its path value; partial config deployments where only some Overlords have the file path property.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/95663baa90e4189d. Report an issue: GitHub.