{"record":{"id":"2954c909032f1cb0","repo":"apache/dolphinscheduler","slug":"fail-to-get-k8s-apiclient-s","errorCode":null,"errorMessage":"fail to get k8s ApiClient:%s","messagePattern":"fail to get k8s ApiClient:(.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sManager.java","lineNumber":115,"sourceCode":"            client.close();\n        }\n    }\n\n    private void createK8sClientInner(Long clusterCode) {\n        Cluster cluster = clusterDao.queryByClusterCode(clusterCode);\n        if (cluster == null) {\n            return;\n        }\n\n        String k8sConfig = ClusterConfUtils.getK8sConfig(cluster.getConfig());\n        if (k8sConfig != null) {\n            KubernetesClient client = null;\n            try {\n                client = getClient(k8sConfig);\n                clientMap.put(clusterCode, client);\n            } catch (Exception e) {\n                log.error(\"cluster code ={},fail to get k8s ApiClient:  {}\", clusterCode, e.getMessage());\n                throw new RuntimeException(\"fail to get k8s ApiClient:\" + e.getMessage());\n            }\n        }\n    }\n\n    private KubernetesClient getClient(String configYaml) throws RuntimeException {\n        try {\n            Config config = Config.fromKubeconfig(configYaml);\n            return new KubernetesClientBuilder().withConfig(config).build();\n        } catch (Exception e) {\n            log.error(\"Fail to get k8s ApiClient\", e);\n            throw new RuntimeException(\"fail to get k8s ApiClient:\" + e.getMessage());\n        }\n    }\n\n}\n","sourceCodeStart":97,"sourceCodeEnd":131,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sManager.java#L97-L131","documentation":"K8sManager.createK8sClientInner wraps any failure to build a KubernetesClient for a cluster (clusterCode -> configYaml from the cluster table) in a RuntimeException with this message. getClient() parses the kubeconfig YAML and constructs a client via fabric8 KubernetesClientBuilder; any parse or construction error is rethrown here. The root cause's stack trace is only logged, not propagated.","triggerScenarios":"getAndUpdateK8sClient(clusterCode) is called and getClient(k8sConfig) throws - typically because the cluster's k8s_config holds invalid/empty YAML, an expired/rotated credential, or the fabric8 client cannot be constructed from the config.","commonSituations":"Cluster config pasted with wrong indentation or unsubstituted placeholders; kubeconfig from an old cluster after migration; malformed base64 certificate data; fabric8 client version incompatibility with the target cluster.","solutions":["Fix the k8s_config YAML stored for the cluster (verify with `kubectl --kubeconfig <file> cluster-info`)","Check the application log just above the exception for the logged root cause with full stack trace","Re-enter cluster credentials via the UI/API after a credential rotation","Verify the fabric8 kubernetes-client dependency version is compatible with the target cluster"],"exampleFix":"// before: ambiguous rethrow loses stack\nthrow new RuntimeException(\"fail to get k8s ApiClient:\" + e.getMessage());\n// after: preserve cause\nthrow new RuntimeException(\"fail to get k8s ApiClient:\" + e.getMessage(), e);","handlingStrategy":"validation","validationCode":"// before calling getAndUpdateK8sClient\nif (cluster.getK8sConfig() == null || cluster.getK8sConfig().isBlank()) {\n    throw new IllegalArgumentException(\"cluster \" + clusterCode + \" has empty k8s config\");\n}\ntry { new Yaml(new Constructor(io.fabric8.kubernetes.api.model.Config.class)).load(cluster.getK8sConfig()); }\ncatch (Exception e) { throw new IllegalArgumentException(\"invalid kubeconfig yaml: \" + e.getMessage()); }","typeGuard":"boolean hasValidKubeconfig(Cluster c) {\n    return c != null && c.getK8sConfig() != null && c.getK8sConfig().contains(\"clusters:\")\n        && c.getK8sConfig().contains(\"server:\");\n}","tryCatchPattern":"try {\n    k8sManager.getAndUpdateK8sClient(clusterCode);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"fail to get k8s ApiClient\")) {\n        log.error(\"K8s client init failed for cluster {}, fix cluster config and retry\", clusterCode, e);\n        // fall back to default client or abort deployment gracefully\n    } else { throw e; }\n}","preventionTips":["Validate kubeconfig YAML with kubectl before saving it into the cluster form","Never store placeholder/unsubstituted kubeconfig templates","Log the root cause exception, not just getMessage()","Test cluster connectivity after every credential rotation"],"tags":["kubernetes","config","client-init"],"backgroundTag":"invalid-config-value","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}