apache/druid · error · IllegalArgumentException

Could not find container named

Error message

Could not find container named: %s in PodSpec

What it means

massageSpec reorders the PodSpec's containers so the configured primary container (druid.k8s.adapter.environment variable K8S_TASK_ADAPTER primary container name) is first. If it iterates through all containers without finding a container whose name matches primaryContainerName, it throws this IllegalArgumentException, because it cannot unambiguously pick which container is the Druid peon.

Solutions

  1. Rename the container in the pod template back to the expected primary container name (default `main`), or
  2. Set the adapter's primary container name config (druid.k8s.task.adapter primary container setting) to match the actual container name in the PodSpec.
  3. Check the task's dynamic config / k8s pod template for typos in the container name.
  4. As a quick check, list container names in the template with `kubectl get podtemplate <name> -o jsonpath='{.template.spec.containers[*].name}'`.

Example fix

// before (pod template)
containers:
  - name: druid-peon
    image: apache/druid:tag
// after
containers:
  - name: main
    image: apache/druid:tag
Defensive patterns

Strategy: validation

Validate before calling

// java
boolean found = podSpec.getContainers().stream()
    .anyMatch(c -> c.getName().equals(primaryContainerName));
if (!found) { throw new IllegalArgumentException("pod spec lacks container " + primaryContainerName); }

Try / catch

// java
try { adapter.toTask(pod); }
catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Could not find container named")) {
    // align container name or primary container config
  }
}

Prevention

When it happens

Trigger: fromTask/toTask on a pod spec whose container names do not include the configured primary container name (default "main"); container renamed in a custom pod template; case mismatch in the name.

Common situations: Teams customize their peon pod template and rename the main container (e.g. to "druid" or "peon") without updating the overlord's primary container config; copy-pasted templates where the container is named differently per environment.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

    podTemplate.setSpec(podSpec);
    return podTemplate;
  }

  @VisibleForTesting
  static void massageSpec(PodSpec spec, String primaryContainerName)
  {
    // find the primary container and make it first,
    if (StringUtils.isNotBlank(primaryContainerName)) {
      int i = 0;
      while (i < spec.getContainers().size()) {
        if (primaryContainerName.equals(spec.getContainers().get(i).getName())) {
          break;
        }
        i++;
      }
      // if the primaryContainer is not found, assume the primary container is the first container.
      if (i >= spec.getContainers().size()) {
        throw new IllegalArgumentException("Could not find container named: "
                                           + primaryContainerName
                                           + " in PodSpec");
      }
      Container primary = spec.getContainers().get(i);
      spec.getContainers().remove(i);
      spec.getContainers().add(0, primary);
    }
  }

  private List<String> javaOpts(Task task)
  {
    final List<String> javaOpts = new ArrayList<>();
    Iterables.addAll(javaOpts, taskRunnerConfig.getJavaOptsArray());

    // Override task specific javaOpts
    Object taskJavaOpts = task.getContextValue(
        ForkingTaskRunnerConfig.JAVA_OPTS_PROPERTY
    );

View on GitHub (pinned to 9b90983fd2)