{"record":{"id":"7bf004dbdefd3c4a","repo":"grpc/grpc-go","slug":"cannot-have-a-leading-slash","errorCode":null,"errorMessage":"cannot have a leading slash","messagePattern":"cannot have a leading slash","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gcp/observability/config.go","lineNumber":61,"sourceCode":"\t// Step 2: Check default credential\n\tcredentials, err := google.FindDefaultCredentials(ctx, gcplogging.WriteScope)\n\tif err != nil {\n\t\tlogger.Infof(\"Failed to locate Google Default Credential: %v\", err)\n\t\treturn \"\"\n\t}\n\tif credentials.ProjectID == \"\" {\n\t\tlogger.Infof(\"Failed to find project ID in default credential: %v\", err)\n\t\treturn \"\"\n\t}\n\tlogger.Infof(\"Found project ID from Google Default Credential: %v\", credentials.ProjectID)\n\treturn credentials.ProjectID\n}\n\n// validateMethodString validates whether the string passed in is a valid\n// pattern.\nfunc validateMethodString(method string) error {\n\tif strings.HasPrefix(method, \"/\") {\n\t\treturn errors.New(\"cannot have a leading slash\")\n\t}\n\tserviceMethod := strings.Split(method, \"/\")\n\tif len(serviceMethod) != 2 {\n\t\treturn errors.New(\"/ must come in between service and method, only one /\")\n\t}\n\tif serviceMethod[1] == \"\" {\n\t\treturn errors.New(\"method name must be non empty\")\n\t}\n\tif serviceMethod[0] == \"*\" {\n\t\treturn errors.New(\"cannot have service wildcard * i.e. (*/m)\")\n\t}\n\treturn nil\n}\n\nfunc validateLogEventMethod(methods []string, exclude bool) error {\n\tfor _, method := range methods {\n\t\tif method == \"*\" {\n\t\t\tif exclude {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/gcp/observability/config.go#L43-L79","documentation":"Returned by validateMethodString (gcp/observability/config.go:61) when the method string passed to an observability logging config starts with '/'. Observability method filters use the form <service>/<method> WITHOUT a leading slash (the leading slash is the gRPC wire format, but the config rejects it). It is reached via validateLogEventMethod -> validateLoggingEvents -> unmarshalAndVerifyConfig while parsing GRPC_GCP_OBSERVABILITY_CONFIG.","triggerScenarios":"Setting client_rpc_events/server_rpc_events methods entries like \"/pkg.Svc/Method\" (with leading slash) in the observability JSON config. Also triggered programmatically if a caller invokes validateMethodString with such input.","commonSituations":"Copy-pasting the method name from grpc method invocations (which use /pkg.Svc/Method on the wire) into the config; docs confusion between wire form and config form; auto-generating config from protobuf full names and prepending '/'","solutions":["Remove the leading '/' from each method entry — use pkg.Svc/Method.","If generating the config programmatically, strings.TrimPrefix(method, \"/\") each entry.","Validate your config JSON against the documented form before deploying."],"exampleFix":"// before (env var)\nGRPC_GCP_OBSERVABILITY_CONFIG='{\"project_id\":\"p\",\"cloud_logging\":{\"client_rpc_events\":[{\"methods\":[\"/foo.Bar/Baz\"]}]}}'\n// error: cannot have a leading slash\n\n// after\nGRPC_GCP_OBSERVABILITY_CONFIG='{\"project_id\":\"p\",\"cloud_logging\":{\"client_rpc_events\":[{\"methods\":[\"foo.Bar/Baz\"]}]}}'","handlingStrategy":"validation","validationCode":"// Mirror the library's rule to catch bad entries before/after config parse.\nfunc validateMethod(method string) error {\n    if strings.HasPrefix(method, \"/\") {\n        return fmt.Errorf(\"method %q: cannot have a leading slash\", method)\n    }\n    parts := strings.Split(method, \"/\")\n    if len(parts) != 2 {\n        return fmt.Errorf(\"method %q: need exactly one '/'\", method)\n    }\n    if parts[1] == \"\" {\n        return fmt.Errorf(\"method %q: method name empty\", method)\n    }\n    return nil\n}\nfor _, m := range cfgMethods {\n    m = strings.TrimPrefix(m, \"/\") // auto-fix leading slash\n    if err := validateMethod(m); err != nil { return err }\n}","typeGuard":null,"tryCatchPattern":"cfg, err := parseObservabilityConfig()\nif err != nil { log.Fatalf(\"observability config: %v\", err) }","preventionTips":["Lint observability config in CI before deploying.","Generate methods from protobuf full names and strip the leading '/' deliberately."],"tags":["go","grpc","observability","config-validation","logging"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}