{"record":{"id":"27b26e310bd042dc","repo":"grpc-ecosystem/grpc-gateway","slug":"failed-to-parse-grpc-api-configuration-from-yaml-i","errorCode":null,"errorMessage":"failed to parse gRPC API Configuration from YAML in %q: %w","messagePattern":"failed to parse gRPC API Configuration from YAML in %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/descriptor/grpc_api_configuration.go","lineNumber":17,"sourceCode":"package descriptor\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/apiconfig\"\n\t\"go.yaml.in/yaml/v3\"\n\t\"google.golang.org/protobuf/encoding/protojson\"\n)\n\nfunc loadGrpcAPIServiceFromYAML(yamlFileContents []byte, yamlSourceLogName string) (*apiconfig.GrpcAPIService, error) {\n\tvar yamlContents interface{}\n\tif err := yaml.Unmarshal(yamlFileContents, &yamlContents); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse gRPC API Configuration from YAML in %q: %w\", yamlSourceLogName, err)\n\t}\n\n\tjsonContents, err := json.Marshal(yamlContents)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// As our GrpcAPIService is incomplete, accept unknown fields.\n\tunmarshaler := protojson.UnmarshalOptions{\n\t\tDiscardUnknown: true,\n\t}\n\n\tserviceConfiguration := apiconfig.GrpcAPIService{}\n\tif err := unmarshaler.Unmarshal(jsonContents, &serviceConfiguration); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse gRPC API Configuration from YAML in %q: %w\", yamlSourceLogName, err)\n\t}\n\n\treturn &serviceConfiguration, nil","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/internal/descriptor/grpc_api_configuration.go#L1-L35","documentation":"loadGrpcAPIServiceFromYAML wraps yaml.Unmarshal failures when the gRPC API Configuration file is not parseable YAML at all (syntax error, tabs, malformed structure). The function first decodes to generic interface{}, so this fires before any proto validation.","triggerScenarios":"Passing invalid YAML bytes to descriptor.LoadGrpcAPIServiceFromYAML (or via protoc --grpc-gateway_config_file) where yaml.Unmarshal fails — e.g. bad indentation, tabs, duplicate keys, non-mapping top-level types like a bare list or scalar.","commonSituations":"Hand-edited gateway YAML config with indentation/tab mistakes; config file accidentally containing JSON-incompatible or truncated content; CI pointing at the wrong file (e.g. a lockfile passed as config); tests like TestLoadGrpcAPIServiceFromYAMLRejectInvalidYAML exercising this deliberately.","solutions":["Validate the YAML with a linter (yamllint) or by loading it in an editor with YAML syntax checking; fix indentation (spaces, not tabs)","Ensure the top-level structure is a YAML mapping suitable for GrpcAPIService","Confirm the file path passed to protoc --grpc-gateway_config_file points to the intended config"],"exampleFix":"// before (invalid YAML: tab indentation)\nhttp:\n\t_rules:\n// after\nhttp:\n  rules:\n    - selector: pkg.Service.Method\n      get: /v1/things","handlingStrategy":"validation","validationCode":"// before loading config in CI\ndata, err := os.ReadFile(cfgPath)\nif err != nil { return err }\nvar probe interface{}\nif err := yaml.Unmarshal(data, &probe); err != nil {\n    return fmt.Errorf(\"%s is not valid YAML: %w\", cfgPath, err)\n}","typeGuard":null,"tryCatchPattern":"cfg, err := descriptor.LoadGrpcAPIServiceFromYAML(data, cfgPath)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to parse gRPC API Configuration from YAML\") {\n        grpclog.Fatalf(\"fix YAML syntax in %s: %v\", cfgPath, err)\n    }\n    return err\n}","preventionTips":["Run yamllint on gateway config files in CI before protoc runs","Use spaces, never tabs, for YAML indentation","Confirm the path passed to protoc --grpc-gateway_config_file is the intended config"],"tags":["go","yaml","grpc-gateway","config"],"backgroundTag":"yaml-parse-error","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}