{"record":{"id":"3645bd214c88f87d","repo":"grafana/k6","slug":"invalid-tls-password-value-v-it-needs-to-be","errorCode":null,"errorMessage":"invalid tls password value: '%#v', it needs to be a string","messagePattern":"invalid tls password value: '%#v', it needs to be a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/params.go","lineNumber":240,"sourceCode":"\tparams.TLS, ok = v.(map[string]any)\n\n\tif !ok {\n\t\treturn fmt.Errorf(\"invalid tls value: '%#v', expected (optional) keys: cert, key, password, and cacerts\", v)\n\t}\n\t// optional map keys below\n\tif cert, certok := params.TLS[\"cert\"]; certok {\n\t\tif _, ok = cert.(string); !ok {\n\t\t\treturn fmt.Errorf(\"invalid tls cert value: '%#v', it needs to be a PEM formatted string\", v)\n\t\t}\n\t}\n\tif key, keyok := params.TLS[\"key\"]; keyok {\n\t\tif _, ok = key.(string); !ok {\n\t\t\treturn fmt.Errorf(\"invalid tls key value: '%#v', it needs to be a PEM formatted string\", v)\n\t\t}\n\t}\n\tif pass, passok := params.TLS[\"password\"]; passok {\n\t\tif _, ok = pass.(string); !ok {\n\t\t\treturn fmt.Errorf(\"invalid tls password value: '%#v', it needs to be a string\", v)\n\t\t}\n\t}\n\tif cacerts, cacertsok := params.TLS[\"cacerts\"]; cacertsok {\n\t\tvar cacertsArray []any\n\t\tif cacertsArray, ok = cacerts.([]any); ok {\n\t\t\tfor _, cacertsArrayEntry := range cacertsArray {\n\t\t\t\tif _, ok = cacertsArrayEntry.(string); !ok {\n\t\t\t\t\treturn fmt.Errorf(\"invalid tls cacerts value: '%#v',\"+\n\t\t\t\t\t\t\" it needs to be a string or an array of PEM formatted strings\", v)\n\t\t\t\t}\n\t\t\t}\n\t\t} else if _, ok = cacerts.(string); !ok {\n\t\t\treturn fmt.Errorf(\"invalid tls cacerts value: '%#v',\"+\n\t\t\t\t\" it needs to be a string or an array of PEM formatted strings\", v)\n\t\t}\n\t}\n\treturn nil\n}","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/params.go#L222-L258","documentation":"Thrown by k6's gRPC Client.connect() when tls.password is present but not a string. parseConnectTLSParam (internal/js/modules/k6/grpc/params.go:238-241) validates only the type: the passphrase used to decrypt an encrypted client private key must be a string. The message again prints the whole tls map (v), not just the password value.","triggerScenarios":"tls: { cert, key, password: 12345 }, password: true, or password: ['secret']. Any non-string value under tls.password triggers this before a connection is attempted.","commonSituations":"Reading the passphrase from an environment variable or config system that yields a non-string (number, object); leaving a placeholder like password: null after debugging.","solutions":["Coerce the passphrase to a string before passing: password: String(__ENV.KEY_PASS).","If the key is not encrypted, remove the password entry entirely.","Verify with typeof password === 'string' in script setup code before connect()."],"exampleFix":"// before\nclient.connect('host:443', { tls: { cert, key, password: 12345 } });\n\n// after\nclient.connect('host:443', { tls: { cert, key, password: String(__ENV.KEY_PASS) } });","handlingStrategy":"validation","validationCode":"function validateTls(tls = {}) {\n  if ('password' in tls && typeof tls.password !== 'string') throw new Error('tls.password must be a string');\n}","typeGuard":"const isOptionalString = (v) => v === undefined || typeof v === 'string';","tryCatchPattern":null,"preventionTips":["Wrap env-sourced passphrases with String(...) at init time.","Drop the password key entirely for unencrypted keys."],"tags":["grpc","tls","validation","password"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}