{"record":{"id":"abbe45e03e704a34","repo":"apache/druid","slug":"must-have-at-least-one-container","errorCode":null,"errorMessage":"Must have at least one container","messagePattern":"Must have at least one container","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/K8sTaskAdapter.java","lineNumber":357,"sourceCode":"      );\n    }\n    mainContainer.getEnv().addAll(envVars);\n  }\n\n  protected Container setupMainContainer(\n      PodSpec podSpec,\n      PeonCommandContext context,\n      long containerSize,\n      String taskContents\n  ) throws JsonProcessingException\n  {\n    // prepend the startup task.json extraction command\n    List<String> mainCommand = Lists.newArrayList(\"sh\", \"-c\");\n    // update the command\n    List<Container> containers = podSpec.getContainers();\n    Container mainContainer = Iterables.getFirst(containers, null);\n    if (mainContainer == null) {\n      throw new IllegalArgumentException(\"Must have at least one container\");\n    }\n\n    // remove probes\n    mainContainer.setReadinessProbe(null);\n    mainContainer.setLivenessProbe(null);\n    mainContainer.setStartupProbe(null);\n\n    setupPorts(mainContainer);\n    addEnvironmentVariables(mainContainer, context, taskContents);\n\n    mainContainer.setCommand(mainCommand);\n    mainContainer.setArgs(Collections.singletonList(Joiner.on(\" \").join(context.getCommand())));\n\n    mainContainer.setName(\"main\");\n    ResourceRequirements requirements = getResourceRequirements(\n        mainContainer.getResources(),\n        containerSize,\n        context.getCpuMicroCore()","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/K8sTaskAdapter.java#L339-L375","documentation":"K8sTaskAdapter throws this IllegalArgumentException when converting a task's PodSpec and finds no containers at all in the pod spec. The adapter must locate the first container to inject the task.json extraction command and strip readiness/liveness/startup probes; without any container it cannot build a valid peon pod. This is a guard against a malformed or empty PodSpec.","triggerScenarios":"Calling setupMainContainer (via fromTask/toTask conversion) with a PodSpec whose getContainers() list is empty or null-derived empty, e.g. a task spec or pod template with no containers defined.","commonSituations":"Custom k8s pod template files (druid-k8s podTemplate or task adapter config) that omit the `containers:` section entirely; YAML indentation mistakes that drop containers; building task JSON programmatically without adding a container.","solutions":["Ensure the task's PodSpec (or referenced pod template) declares at least one container, typically the main druid peon container.","Check the k8s pod template YAML for missing or mis-indented `containers:` entries and re-apply it.","Verify druid.k8s.task.adapter pod template path configuration points at the correct template file.","If constructing the task JSON in code, call podSpec.getContainers().add(...) before submitting the task."],"exampleFix":"// before (task pod template YAML)\nspec:\n  restartPolicy: Never\n// after\nspec:\n  restartPolicy: Never\n  containers:\n    - name: main\n      image: apache/druid:tag","handlingStrategy":"validation","validationCode":"// java\nif (podSpec.getContainers() == null || podSpec.getContainers().isEmpty()) {\n  throw new IllegalArgumentException(\"task pod template must define at least one container\");\n}","typeGuard":null,"tryCatchPattern":"// java\ntry { adapter.fromTask(task); }\ncatch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"Must have at least one container\")) {\n    // fix pod template and re-submit\n  }\n}","preventionTips":["Always include a `main` container in peon pod templates.","Validate pod template YAML with kubectl apply --dry-run=server before wiring it into Druid config.","Add a CI check that parses the pod template and asserts containers is non-empty."],"tags":["kubernetes","task-adapter","pod-spec","configuration"],"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"}