{"record":{"id":"8366888052c0b11c","repo":"apache/pulsar","slug":"no-functioncontainer-found","errorCode":null,"errorMessage":"No FunctionContainer found","messagePattern":"No FunctionContainer found","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/secrets/src/main/java/org/apache/pulsar/functions/secretsproviderconfigurator/KubernetesSecretsProviderConfigurator.java","lineNumber":83,"sourceCode":"    }\n\n    // Kubernetes secrets can be exposed as volume mounts or as\n    // environment variables in the pods. We are currently using the\n    // environment variables way. Essentially the secretName/secretPath\n    // is attached as secretRef to the environment variables\n    // of a pod and kubernetes magically makes the secret pointed to by this combination available as a env variable.\n    @Override\n    public void configureKubernetesRuntimeSecretsProvider(V1PodSpec podSpec, String functionsContainerName,\n                                                          FunctionDetails functionDetails) {\n        V1Container container = null;\n        for (V1Container v1Container : podSpec.getContainers()) {\n            if (v1Container.getName().equals(functionsContainerName)) {\n                container = v1Container;\n                break;\n            }\n        }\n        if (container == null) {\n            throw new RuntimeException(\"No FunctionContainer found\");\n        }\n        if (!StringUtils.isEmpty(functionDetails.getSecretsMap())) {\n            Type type = new TypeToken<Map<String, Object>>() {\n            }.getType();\n            Map<String, Object> secretsMap = new Gson().fromJson(functionDetails.getSecretsMap(), type);\n            for (Map.Entry<String, Object> entry : secretsMap.entrySet()) {\n                final V1EnvVar secretEnv = new V1EnvVar();\n                @SuppressWarnings(\"unchecked\") // secret values are expected to be Map<String, String>\n                Map<String, String> kv = (Map<String, String>) entry.getValue();\n                secretEnv.name(entry.getKey())\n                        .valueFrom(new V1EnvVarSource()\n                                .secretKeyRef(new V1SecretKeySelector()\n                                        .name(kv.get(idKey))\n                                        .key(kv.get(keyKey))));\n                container.addEnvItem(secretEnv);\n            }\n        }\n    }","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/secrets/src/main/java/org/apache/pulsar/functions/secretsproviderconfigurator/KubernetesSecretsProviderConfigurator.java#L65-L101","documentation":"KubernetesSecretsProviderConfigurator.configureKubernetesRuntimeSecretsProvider() scans the function pod spec's containers for one named functionsContainerName (typically 'function'). If no container matches after the loop, it throws RuntimeException(\"No FunctionContainer found\") because it cannot attach secret env vars to the pod spec.","triggerScenarios":"Submitting/configuring a function on Kubernetes where the generated (or provided) pod spec has no container literally named after functionsContainerName — e.g. custom pod specs renamed the container, or the function worker built the pod without the expected 'function' container.","commonSituations":"Customized KubernetesRuntimeFactory container names; user-supplied pod templates overriding the container name; version changes where the default container name changed; mutating webhooks rewriting container names.","solutions":["Ensure the function pod spec includes a container named 'function' (the default functionsContainerName), or update functionsContainerName in the worker's KubernetesRuntimeFactory config to match your custom container name.","Remove/fix custom pod.yaml templates that rename the container.","Check function worker config (k8s runtime settings) so the container name matches between pod creation and secrets configuration.","Inspect the generated pod spec (kubectl get pod -o jsonpath='{.spec.containers[*].name}') to confirm names."],"exampleFix":"// before (custom pod template)\ncontainers:\n  - name: my-fn-container\n    image: ...\n// after\ncontainers:\n  - name: function\n    image: ...","handlingStrategy":"validation","validationCode":"boolean hasFunctionContainer = java.util.Arrays.stream(podSpec.getContainers())\n  .anyMatch(c -> c.getName().equals(\"function\"));\nif (!hasFunctionContainer) throw new IllegalStateException(\"Pod spec must contain a container named 'function'\");","typeGuard":"boolean podHasFunctionContainer(io.kubernetes.client.openapi.models.V1PodSpec spec, String name) {\n  return spec != null && spec.getContainers() != null\n    && spec.getContainers().stream().anyMatch(c -> name.equals(c.getName()));\n}","tryCatchPattern":"try { configurator.configureKubernetesRuntimeSecretsProvider(functionDetails, podSpec, containerName); } catch (RuntimeException e) { if (\"No FunctionContainer found\".equals(e.getMessage())) { log.error(\"Pod containers: {}\", java.util.Arrays.toString(podSpec.getContainers().stream().map(c -> c.getName()).toArray())); } throw e; }","preventionTips":["Never rename the 'function' container in custom pod templates.","Keep functionsContainerName config consistent with pod spec generation.","Audit mutating webhooks that rewrite container names.","Log container names from pod specs when debugging k8s function runtime."],"tags":["kubernetes","pod-spec","secrets-provider","configuration"],"backgroundTag":"missing-container-in-pod","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}