{"record":{"id":"b1b92814a30a803a","repo":"grpc/grpc-go","slug":"missing-fallback-credentials","errorCode":null,"errorMessage":"missing fallback credentials","messagePattern":"missing fallback credentials","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/xds/xds.go","lineNumber":50,"sourceCode":"\txdsinternal \"google.golang.org/grpc/internal/credentials/xds\"\n\t\"google.golang.org/grpc/internal/grpcsync\"\n)\n\n// ClientOptions contains parameters to configure a new client-side xDS\n// credentials implementation.\ntype ClientOptions struct {\n\t// FallbackCreds specifies the fallback credentials to be used when either\n\t// the `xds` scheme is not used in the user's dial target or when the\n\t// management server does not return any security configuration. Attempts to\n\t// create client credentials without fallback credentials will fail.\n\tFallbackCreds credentials.TransportCredentials\n}\n\n// NewClientCredentials returns a new client-side transport credentials\n// implementation which uses xDS APIs to fetch its security configuration.\nfunc NewClientCredentials(opts ClientOptions) (credentials.TransportCredentials, error) {\n\tif opts.FallbackCreds == nil {\n\t\treturn nil, errors.New(\"missing fallback credentials\")\n\t}\n\treturn &credsImpl{\n\t\tisClient: true,\n\t\tfallback: opts.FallbackCreds,\n\t}, nil\n}\n\n// ServerOptions contains parameters to configure a new server-side xDS\n// credentials implementation.\ntype ServerOptions struct {\n\t// FallbackCreds specifies the fallback credentials to be used when the\n\t// management server does not return any security configuration. Attempts to\n\t// create server credentials without fallback credentials will fail.\n\tFallbackCreds credentials.TransportCredentials\n}\n\n// NewServerCredentials returns a new server-side transport credentials\n// implementation which uses xDS APIs to fetch its security configuration.","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/credentials/xds/xds.go#L32-L68","documentation":"Returned by xds.NewClientCredentials when ClientOptions.FallbackCreds is nil. xDS client credentials require fallback TransportCredentials because the management server may not always provide security configuration (e.g., when the xds:// scheme is not used in the dial target). The fallback ensures the channel can still establish a connection in those cases.","triggerScenarios":"Calling xds.NewClientCredentials(xds.ClientOptions{}) without setting FallbackCreds. The nil check rejects this immediately.","commonSituations":"Developers adopt xDS credentials but forget that a fallback is mandatory. Or they intend to use xDS-only security and pass nil, not realizing the design requires fallback for non-xDS targets.","solutions":["Set ClientOptions.FallbackCreds to a valid TransportCredentials instance, typically credentials.NewTLS(tlsConfig) or insecure.NewCredentials().","Use the same fallback you would have used without xDS credentials (your existing TLS config is usually correct)."],"exampleFix":"// before\ncreds, err := xds.NewClientCredentials(xds.ClientOptions{}) // error\n// after\ncreds, err := xds.NewClientCredentials(xds.ClientOptions{\n    FallbackCreds: credentials.NewTLS(&tls.Config{}),\n})","handlingStrategy":"validation","validationCode":"if opts.FallbackCreds == nil {\n    opts.FallbackCreds = credentials.NewTLS(&tls.Config{}) // or insecure.NewCredentials()\n}\ncreds, err := xds.NewClientCredentials(opts)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set FallbackCreds when creating xDS client credentials.","Use your existing TLS config as the fallback.","Add a unit test asserting FallbackCreds is non-nil."],"tags":["go","grpc","xds","credentials","validation"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}