{"record":{"id":"460cb524a360d8a3","repo":"grafana/k6","slug":"failed-to-load-tls-credentials-from-file-w","errorCode":null,"errorMessage":"failed to load TLS credentials from file: %w","messagePattern":"failed to load TLS credentials from file: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloudapi/insights/client.go","lineNumber":228,"sourceCode":"\tif cfg.ConnectConfig.Block {\n\t\topts = append(opts, grpc.WithBlock()) //nolint:staticcheck\n\t}\n\n\tif cfg.ConnectConfig.FailOnNonTempDialError {\n\t\topts = append(opts, grpc.FailOnNonTempDialError(true)) //nolint:staticcheck\n\t}\n\n\tif cfg.ConnectConfig.Dialer != nil {\n\t\topts = append(opts, grpc.WithContextDialer(cfg.ConnectConfig.Dialer))\n\t}\n\n\tif cfg.TLSConfig.Insecure { //nolint: nestif\n\t\topts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))\n\t} else {\n\t\tif cfg.TLSConfig.CertFile != \"\" {\n\t\t\tcreds, err := credentials.NewClientTLSFromFile(cfg.TLSConfig.CertFile, \"\")\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to load TLS credentials from file: %w\", err)\n\t\t\t}\n\t\t\topts = append(opts, grpc.WithTransportCredentials(creds))\n\t\t} else {\n\t\t\topts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{MinVersion: tls.VersionTLS13})))\n\t\t}\n\t}\n\n\tif cfg.AuthConfig.Enabled {\n\t\topts = append(opts, grpc.WithPerRPCCredentials(newPerRPCCredentials(cfg.AuthConfig)))\n\t}\n\n\trI, err := retryInterceptor(cfg.RetryConfig)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create retry interceptors: %w\", err)\n\t}\n\n\topts = append(opts, grpc.WithChainUnaryInterceptor([]grpc.UnaryClientInterceptor{rI}...))\n","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/cloudapi/insights/client.go#L210-L246","documentation":"When the insights gRPC client is configured with a TLS cert file (TLSConfig.CertFile), dial options construction calls credentials.NewClientTLSFromFile (internal/cloudapi/insights/client.go:225-229). Any failure reading or parsing that file - missing path, permission denied, content that is not a PEM certificate bundle - returns this wrapped error and Dial aborts.","triggerScenarios":"CertFile set to a path that does not exist in k6's container/filesystem; a mounted secret that is empty or corrupt; a file containing keys but no certificates; relative path resolved against an unexpected working directory.","commonSituations":"Kubernetes secret mounted at a different path than configured; CI copying the CA with the wrong name; PEM bundle truncated in transit; permissions blocking read.","solutions":["Verify the exact path exists and is readable from where k6 runs: 'ls -l /path/ca.pem' inside the same container","Validate the file is a PEM certificate: 'openssl x509 -in /path/ca.pem -text -noout' (and check the bundle contains certs)","Use an absolute path in the configuration to avoid working-directory surprises","Re-mount or re-copy the secret if it is empty/corrupt"],"exampleFix":"# before - path valid on the host, not in the container\nvolumeMounts: [{ name: ca, mountPath: /etc/ca }]   # file lands at /etc/ca/ca.pem\nconfig: certFile: /etc/ca.pem   # wrong\n\n# after\nconfig: certFile: /etc/ca/ca.pem","handlingStrategy":"validation","validationCode":"# deployment pre-flight for the insights CA file\nCERT=/etc/k6/insights-ca.pem\n[ -s \"$CERT\" ] || { echo \"cert file missing/empty: $CERT\"; exit 1; }\nopenssl x509 -in \"$CERT\" -noout >/dev/null || { echo \"not a valid PEM cert: $CERT\"; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mount CA secrets at fixed absolute paths and reference exactly those paths in config","Validate PEM bundles in CI (openssl x509) before any run that uses custom CAs","Watch for empty Kubernetes secrets - a missing key mounts an empty file"],"tags":["tls","grpc","insights","configuration","file","cloud"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}