{"record":{"id":"d22b5312110017e3","repo":"testcontainers/testcontainers-java","slug":"clusters-0-cluster-expected-to-be-an-object","errorCode":null,"errorMessage":"'/clusters/0/cluster' expected to be an object","messagePattern":"'/clusters/0/cluster' expected to be an object","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"modules/k3s/src/main/java/org/testcontainers/k3s/K3sContainer.java","lineNumber":97,"sourceCode":"     */\n    public String generateInternalKubeConfigYaml(String networkAlias) {\n        if (this.getNetworkAliases().contains(networkAlias)) {\n            String serverUrl = \"https://\" + networkAlias + \":\" + KUBE_SECURE_PORT;\n            return kubeConfigWithServerUrl(kubeConfigYaml, serverUrl);\n        } else {\n            throw new IllegalArgumentException(networkAlias + \" is not a network alias for k3s container\");\n        }\n    }\n\n    @SneakyThrows\n    private String kubeConfigWithServerUrl(String kubeConfigYaml, String serverUrl) {\n        ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());\n\n        ObjectNode kubeConfigObjectNode = objectMapper.readValue(kubeConfigYaml, ObjectNode.class);\n\n        JsonNode clusterNode = kubeConfigObjectNode.at(\"/clusters/0/cluster\");\n        if (!clusterNode.isObject()) {\n            throw new IllegalStateException(\"'/clusters/0/cluster' expected to be an object\");\n        }\n        ObjectNode clusterConfig = (ObjectNode) clusterNode;\n        clusterConfig.replace(\"server\", new TextNode(serverUrl));\n\n        kubeConfigObjectNode.set(\"current-context\", new TextNode(\"default\"));\n\n        return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(kubeConfigObjectNode);\n    }\n}\n","sourceCodeStart":79,"sourceCodeEnd":107,"githubUrl":"https://github.com/testcontainers/testcontainers-java/blob/8e549514e3f01c57d70546fbb8599d138f3903e5/modules/k3s/src/main/java/org/testcontainers/k3s/K3sContainer.java#L79-L107","documentation":"When rewriting the server URL inside the bundled kubeconfig YAML, K3sContainer parses it with Jackson and expects the path /clusters/0/cluster to be a JSON/YAML object. If the YAML shape changed (parse produced a non-object node, e.g. missing, null, or a different structure), the method aborts with IllegalStateException because it cannot safely replace the 'server' field.","triggerScenarios":"kubeConfigWithServerUrl invoked (directly from generateInternalKubeConfigYaml or via containerIsStarted config update) with a kubeConfigYaml template whose 'clusters[0].cluster' entry is missing, null, or not a mapping — e.g. after editing/replacing the default kubeConfigYaml resource or an incompatible YAML layout.","commonSituations":"Overriding the embedded kubeconfig YAML with a custom file having a different structure; the clusters list is empty; YAML indentation mistakes making 'cluster' a scalar/string; library version whose bundled template changed.","solutions":["Restore/keep the default kubeconfig template shipped with testcontainers-k3s so clusters[0].cluster is a mapping","If customizing the YAML, ensure it contains clusters: - cluster: {server: ..., certificate-authority-data: ...} with correct indentation","Inspect the parsed structure: log the YAML and confirm /clusters/0/cluster is a mapping before calling","Upgrade testcontainers-k3s to a version whose bundled kubeconfig matches the code path"],"exampleFix":"// before (custom kubeconfig with wrong shape)\nclusters: []\n\n// after\nclusters:\n  - name: default\n    cluster:\n      server: https://127.0.0.1:6443\n      certificate-authority-data: <base64>","handlingStrategy":"validation","validationCode":"ObjectNode cfg = new ObjectMapper(new YAMLFactory()).readValue(kubeConfigYaml, ObjectNode.class);\nif (!cfg.at(\"/clusters/0/cluster\").isObject()) {\n  throw new IllegalStateException(\"kubeconfig template missing clusters[0].cluster mapping\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  String yaml = k3s.generateInternalKubeConfigYaml(alias);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"expected to be an object\")) {\n    // regenerate with default bundled kubeconfig or fix the YAML template\n  }\n  throw e;\n}","preventionTips":["Do not modify the embedded kubeconfigYaml template unless keeping clusters[0].cluster as a mapping","Validate custom kubeconfig YAML with a linter before using it in tests","Pin testcontainers-k3s versions to avoid template drift","Add a smoke test calling generateInternalKubeConfigYaml in CI"],"tags":["k3s","yaml","kubeconfig"],"backgroundTag":"unexpected-response-shape","analyzedSha":"8e549514e3f01c57d70546fbb8599d138f3903e5","analyzedAt":"2026-09-12T14:56:41.227Z","contentChangedAt":"2026-09-12T14:56:41.227Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}