{"record":{"id":"a1a94e8fad188ede","repo":"theonedev/onedev","slug":"shell-not-ready","errorCode":null,"errorMessage":"Shell not ready","messagePattern":"Shell not ready","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-plugin/server-plugin-executor-kubernetes/src/main/java/io/onedev/server/plugin/executor/kubernetes/KubernetesExecutor.java","lineNumber":369,"sourceCode":"\t\t\t\tString containerNameCopy = containerName;\n\t\t\t\tif (containerNameCopy != null) {\n\t\t\t\t\tCommandline kubectl = newKubectl();\n\t\t\t\t\tkubectl.addArgs(\"exec\", \"-it\", POD_NAME, \"-c\", containerNameCopy,\n\t\t\t\t\t\t\t\"--namespace\", getNamespace(jobContext), \"--\");\n\n\t\t\t\t\tString shell = null;\n\t\t\t\t\tif (containerNameCopy.startsWith(\"step-\")) {\n\t\t\t\t\t\tList<Integer> stepPosition = parseStepPosition(containerNameCopy.substring(\"step-\".length()));\n\t\t\t\t\t\tLeafFacade step = Preconditions.checkNotNull(jobContext.getStep(stepPosition));\n\t\t\t\t\t\tif (step instanceof CommandFacade)\n\t\t\t\t\t\t\tshell = ((CommandFacade)step).getExecutable();\n\t\t\t\t\t}\n\t\t\t\t\tif (shell == null) \n\t\t\t\t\t\tshell = \"sh\";\n\t\t\t\t\tkubectl.addArgs(shell);\n\t\t\t\t\treturn new CommandlineShell(terminal, kubectl);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new ExplicitException(\"Shell not ready\");\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\t}\n\t\n\tprivate JobService getJobService() {\n\t\treturn OneDev.getInstance(JobService.class);\n\t}\n\t\n\tprivate String getNamespace(JobContext jobContext) {\n\t\treturn getName() + \"-\" + jobContext.getProjectId() + \"-\" \n\t\t\t\t+ jobContext.getBuildNumber() + \"-\" + jobContext.getSubmitSequence();\n\t}\n\n\tprivate String getTestNamespace() {\n\t\treturn getName() + \"-executor-test\";\n\t}\n","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-executor-kubernetes/src/main/java/io/onedev/server/plugin/executor/kubernetes/KubernetesExecutor.java#L351-L387","documentation":"KubernetesExecutor.openShell opens an interactive shell (kubectl exec) into a pod. The inner logic first tries to find a suitable shell binary in the container; if the container's command inspection fails or no shell can be determined and the fallback path is not reached, it throws this ExplicitException meaning the shell could not be prepared.","triggerScenarios":"Calling openShell against a pod whose container does not have a usable shell (or the shell detection path fails) so the code reaches the else branch with shell still null and no 'sh' fallback applied.","commonSituations":"Distroless or minimal container images (scratch, distroless) that ship no shell at all; images where sh/bash are in non-standard locations; pod not fully running when the shell is opened.","solutions":["Install a shell (sh/bash) in the container image, e.g. use a base image that includes busybox or bash","If building the image is not possible, run a debug sidecar/ephemeral container that has a shell","Ensure the pod/container is in Running state before opening a shell","Verify the executor's shell detection logic covers your image's shell path"],"exampleFix":"// before (Dockerfile)\nFROM gcr.io/distroless/java\n// after\nFROM gcr.io/distroless/java:debug  # includes busybox shell\n// or add a shell in a regular image:\nRUN apt-get update && apt-get install -y busybox","handlingStrategy":"validation","validationCode":"// Ensure the target container image contains a shell before opening one\n// e.g. verify with: kubectl exec <pod> -- sh -c 'command -v sh || command -v bash'\nboolean containerHasShell = execInPod(pod, \"command -v sh || command -v bash\") != null;\nif (!containerHasShell) throw new IllegalStateException(\"No shell in container; use a debug image\");","typeGuard":null,"tryCatchPattern":"try (ShellSession session = executor.openShell(pod)) { ... } catch (ExplicitException e) { logger.warn(\"Shell unavailable: {}\", e.getMessage()); }","preventionTips":["Use container images that include a shell (add busybox if minimal)","Test kubectl exec into the pod manually before automating","Wait for pod Running/Ready state before opening shells"],"tags":["kubernetes","shell","kubectl","container"],"backgroundTag":"command-not-found","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}