grpc-ecosystem/grpc-gateway · error
failed to read gRPC API Configuration description from %q: %
Error message
failed to read gRPC API Configuration description from %q: %w
What it means
Registry.LoadGrpcAPIServiceFromYAML wraps os.ReadFile failures when loading a gRPC API Configuration (grpc.gateway.protoc_gen_openapiv2.options) YAML file. It means the YAML config file could not be read from disk at all, before any parsing happened. The underlying OS error is preserved via %w.
Source
Thrown at internal/descriptor/grpc_api_configuration.go:68
registry.AddExternalHTTPRule(selector, rule)
}
return nil
}
// LoadGrpcAPIServiceFromYAML loads a gRPC API Configuration from the given YAML file
// and registers the HttpRule descriptions contained in it as externalHTTPRules in
// the given registry. This must be done before loading the proto file.
//
// You can learn more about gRPC API Service descriptions from Google's documentation
// at https://cloud.google.com/endpoints/docs/grpc/grpc-service-config
//
// Note that for the purposes of the gateway generator we only consider a subset of all
// available features google supports in their service descriptions.
func (r *Registry) LoadGrpcAPIServiceFromYAML(yamlFile string) error {
yamlFileContents, err := os.ReadFile(yamlFile)
if err != nil {
return fmt.Errorf("failed to read gRPC API Configuration description from %q: %w", yamlFile, err)
}
service, err := loadGrpcAPIServiceFromYAML(yamlFileContents, yamlFile)
if err != nil {
return err
}
return registerHTTPRulesFromGrpcAPIService(r, service, yamlFile)
}
View on GitHub (pinned to a58a4436a3)
Solutions
- Verify the YAML file exists at the exact path passed (ls <path>) and fix the path
- Run protoc from the directory where the config path is relative, or pass an absolute path
- Check file permissions (readable by the user running protoc)
- Ensure the config file is generated/copied before the protoc step runs in CI
Example fix
// before protoc --openapiv2_out=... --openapiv2_opt=grpc_api_configuration=./apiconf,yaml my.proto // after protoc --openapiv2_out=... --openapiv2_opt=grpc_api_configuration=$(pwd)/apiconf.yaml my.proto
Defensive patterns
Strategy: validation
Validate before calling
const path = "apiconf.yaml"
if _, err := os.Stat(path); err != nil {
return fmt.Errorf("gRPC API config %q not readable before load: %w", path, err)
} Try / catch
cfg, err := reg.LoadGrpcAPIServiceFromYAML(path)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) {
log.Fatalf("config file %q unreadable: %v", pe.Path, pe.Err)
}
return err
} Prevention
- Use absolute paths or make paths relative to a known base dir
- Check file existence in the build script before protoc
- Keep config files in the repo so they always exist
- Verify permissions in CI containers (non-root users)
When it happens
Trigger: Calling LoadGrpcAPIServiceFromYAML(yamlFile) (e.g. via protoc-gen-openapiv2 with the grpc_api_configuration flag) when the file path does not exist, is a directory, or the process lacks read permission.
Common situations: Typo'd or relative config path passed on the protoc command line; file generated in a later build step that hasn't run yet; wrong working directory; CI copying config to a different location than expected.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
AI-assisted analysis of grpc-ecosystem/grpc-gateway@a58a4436a3 (2026-09-02).
Data as JSON: /api/errors/31490a6e01121e34.
Report an issue: GitHub.