{"record":{"id":"489a327eafe6ad54","repo":"grpc/grpc-go","slug":"grpc-no-transport-security-set-use-grpc-withtran","errorCode":null,"errorMessage":"grpc: no transport security set (use grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly or set credentials)","messagePattern":"grpc: no transport security set \\(use grpc\\.WithTransportCredentials\\(insecure\\.NewCredentials\\(\\)\\) explicitly or set credentials\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clientconn.go","lineNumber":90,"sourceCode":"\terrConnDrain = errors.New(\"grpc: the connection is drained\")\n\t// errConnClosing indicates that the connection is closing.\n\terrConnClosing = errors.New(\"grpc: the connection is closing\")\n\t// errConnIdling indicates the connection is being closed as the channel\n\t// is moving to an idle mode due to inactivity.\n\terrConnIdling = errors.New(\"grpc: the connection is closing due to channel idleness\")\n\t// invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default\n\t// service config.\n\tinvalidDefaultServiceConfigErrPrefix = \"grpc: the provided default service config is invalid\"\n\t// PickFirstBalancerName is the name of the pick_first balancer.\n\tPickFirstBalancerName = pickfirst.Name\n)\n\n// The following errors are returned from Dial and DialContext\nvar (\n\t// errNoTransportSecurity indicates that there is no transport security\n\t// being set for ClientConn. Users should either set one or explicitly\n\t// call WithInsecure DialOption to disable security.\n\terrNoTransportSecurity = errors.New(\"grpc: no transport security set (use grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly or set credentials)\")\n\t// errTransportCredsAndBundle indicates that creds bundle is used together\n\t// with other individual Transport Credentials.\n\terrTransportCredsAndBundle = errors.New(\"grpc: credentials.Bundle may not be used with individual TransportCredentials\")\n\t// errNoTransportCredsInBundle indicated that the configured creds bundle\n\t// returned a transport credentials which was nil.\n\terrNoTransportCredsInBundle = errors.New(\"grpc: credentials.Bundle must return non-nil transport credentials\")\n\t// errTransportCredentialsMissing indicates that users want to transmit\n\t// security information (e.g., OAuth2 token) which requires secure\n\t// connection on an insecure connection.\n\terrTransportCredentialsMissing = errors.New(\"grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)\")\n)\n\nvar (\n\tdisconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{\n\t\tName:           \"grpc.subchannel.disconnections\",\n\t\tDescription:    \"EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.\",\n\t\tUnit:           \"{disconnection}\",\n\t\tLabels:         []string{\"grpc.target\"},","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/clientconn.go#L72-L108","documentation":"errNoTransportSecurity (clientconn.go:87-90) is returned by validateTransportCredentials (clientconn.go:480-483) when NewClient/Dial is called with neither TransportCredentials nor a CredsBundle. gRPC requires you to make an explicit security choice: real TLS credentials OR an explicit insecure credential.","triggerScenarios":"grpc.NewClient/Dial/DialContext is invoked with no WithTransportCredentials(...) and no WithCredentialsBundle(...). The check runs during channel init and fails synchronously from the constructor.","commonSituations":"Migrating from the removed grpc.WithInsecure()/grpc.WithBlock() APIs without adding insecure.NewCredentials(); forgetting the credentials DialOption; new sample code copied without the security line; localhost dev dial without TLS.","solutions":["For plaintext/local dev: pass grpc.WithTransportCredentials(insecure.NewCredentials()) (import google.golang.org/grpc/credentials/insecure).","For production: pass grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)) with a proper *tls.Config.","If you need per-RPC auth too, combine WithTransportCredentials + WithPerRPCCredentials (never rely on implicit insecure).","Double-check no DialOption is shadowing/overwriting the credentials slice."],"exampleFix":"// before — no credentials at all\ncc, err := grpc.NewClient(\"passthrough:///localhost:8080\")\n// err: grpc: no transport security set ...\n\n// after — explicit insecure for local dev\nimport \"google.golang.org/grpc/credentials/insecure\"\ncc, err := grpc.NewClient(\"passthrough:///localhost:8080\",\n    grpc.WithTransportCredentials(insecure.NewCredentials()))","handlingStrategy":"validation","validationCode":"// Validate creds are set BEFORE constructing the ClientConn\nfunc mustCreds(c credentials.TransportCredentials) credentials.TransportCredentials {\n    if c == nil {\n        return insecure.NewCredentials() // explicit, never implicit\n    }\n    return c\n}\ncc, err := grpc.NewClient(target, grpc.WithTransportCredentials(mustCreds(tlsOrNone)))\nif err != nil { /* errNoTransportSecurity caught here, at construction */ }","typeGuard":null,"tryCatchPattern":"// NewClient returns this synchronously; handle the constructor error\ncc, err := grpc.NewClient(target, opts...)\nif err != nil {\n    if strings.Contains(err.Error(), \"no transport security set\") {\n        opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))\n        cc, err = grpc.NewClient(target, opts...)\n    }\n}","preventionTips":["Always pass an explicit WithTransportCredentials (TLS or insecure.NewCredentials()).","Never assume a default; there is intentionally no implicit insecure.","Lint Dial/DialContext/NewClient calls for missing credentials."],"tags":["security","credentials","config","grpc-go"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}