{"record":{"id":"5c175de0781d4cb0","repo":"Tencent/WeKnora","slug":"mcp-client-config-and-service-are-required","errorCode":null,"errorMessage":"MCP client config and service are required","messagePattern":"MCP client config and service are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/mcp/client.go","lineNumber":152,"sourceCode":"// signal that carries RFC 9728 protected-resource metadata. It returns a\n// non-nil *OAuthRequiredError ONLY when the server advertised a metadata URL —\n// a bare 401 without metadata is treated as an ordinary auth failure (e.g. a\n// wrong/missing API key) so we don't misdirect the user toward OAuth.\nfunc asOAuthRequired(err error) *OAuthRequiredError {\n\tif err == nil {\n\t\treturn nil\n\t}\n\tvar authErr *transport.AuthorizationRequiredError\n\tif errors.As(err, &authErr) && authErr.ResourceMetadataURL != \"\" {\n\t\treturn &OAuthRequiredError{MetadataURL: authErr.ResourceMetadataURL, Err: err}\n\t}\n\treturn nil\n}\n\n// NewMCPClient creates a new MCP client based on the transport type\nfunc NewMCPClient(config *ClientConfig) (MCPClient, error) {\n\tif config == nil || config.Service == nil {\n\t\treturn nil, fmt.Errorf(\"MCP client config and service are required\")\n\t}\n\tif err := ValidateServiceOutboundURLs(config.Service); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Create HTTP client with timeout\n\ttimeout := 30 * time.Second\n\tif config.Service.AdvancedConfig != nil && config.Service.AdvancedConfig.Timeout > 0 {\n\t\ttimeout = time.Duration(config.Service.AdvancedConfig.Timeout) * time.Second\n\t}\n\n\tclientCfg := secutils.DefaultSSRFSafeHTTPClientConfig()\n\tclientCfg.Timeout = timeout\n\thttpClient := secutils.NewSSRFSafeHTTPClient(clientCfg)\n\n\t// Build headers\n\theaders := make(map[string]string)\n\tfor key, value := range config.Service.Headers {","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/mcp/client.go#L134-L170","documentation":"NewMCPClient validates its input before doing any work: a nil config or a config whose Service field is nil cannot describe a transport, so construction fails immediately with this sentinel-style error. It is a pure programming/config error, not a runtime failure.","triggerScenarios":"Calling NewMCPClient(nil), or with &ClientConfig{} where Service was never set; GetOrCreateClient passing through an unresolved service record.","commonSituations":"Config loading skipped or partially failed so the service entry is missing; a map lookup returning a zero-value struct; wiring bugs where the service pointer is dropped between layers.","solutions":["Ensure the ClientConfig is fully populated — especially the Service field — before calling NewMCPClient","Fix config loading so MCP service definitions are parsed and attached","Add a nil check with a clear log line at the call site to catch wiring bugs early","Validate config at startup rather than at client creation time"],"exampleFix":"// before\nclient, err := NewMCPClient(cfg) // cfg.Service is nil\n// after\nif cfg == nil || cfg.Service == nil {\n    return fmt.Errorf(\"mcp service %q not configured\", serviceID)\n}\nclient, err := NewMCPClient(cfg)","handlingStrategy":"validation","validationCode":"func validateMCPConfig(cfg *ClientConfig) error {\n    if cfg == nil || cfg.Service == nil { return errors.New(\"MCP client config and service are required\") }\n    return nil\n}","typeGuard":"func hasMCPService(cfg *ClientConfig) bool { return cfg != nil && cfg.Service != nil }","tryCatchPattern":"client, err := NewMCPClient(cfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"required\") { return fmt.Errorf(\"mcp service misconfigured: %w\", err) }\n    return err\n}","preventionTips":["Validate full config at application startup, not lazily at client creation","Use constructors/builder functions that cannot produce a Service-less config","Log the service ID at call sites so nil configs are traceable","Add unit tests covering nil and zero-value config paths"],"tags":["configuration","validation","mcp","nil-pointer"],"backgroundTag":"missing-required-config","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}