🚀 Feature
protoc-gen-openapiv3 currently auto-injects a single default response pointing to google.rpc.Status for every operation. This is fine for the "happy path + one error shape" case, but many production gRPC services return multiple distinct error payloads for the same HTTP status code, and there is currently no way to document them in the generated spec.
Use Case
Consider a service where a single endpoint can return 400 Bad Request for two semantically different reasons, each with a different JSON payload structure:
service Service {
rpc Delete(DeleteRequest) returns (google.protobuf.Empty) {
option (google.api.http) = { delete: "/v1/foo/{foo_id}" };
// Can return 400 because:
// - ErrCannotDelete (grpc: FAILED_PRECONDITION) - foo is running
// - ErrNotFound (grpc: INVALID_ARGUMENT) - foo doesn't exist
}
}
The correct OpenAPI representation uses oneOf:
"400": {
"description": "ErrCannotDelete | ErrNotFound",
"content": {
"application/json": {
"schema": {
"oneOf": [
{ "type": "object", "properties": { "error": { "type": "string" } }, "x-error-name": "ErrCannotDelete" },
{ "type": "object", "properties": { "error": { "type": "string" } }, "x-error-name": "ErrNotFound" }
]
}
}
}
}
There is no existing annotation that carries this information into the generator.
The generator should:
- Group declared errors by http_code.
- Emit a single oneOf response schema for codes with more than one error, and a plain schema for codes with exactly one error.
- Keep the auto-injected default: google.rpc.Status for undeclared errors (or suppress it with disable_default_errors).
🚀 Feature
protoc-gen-openapiv3currently auto-injects a single default response pointing to google.rpc.Status for every operation. This is fine for the "happy path + one error shape" case, but many production gRPC services return multiple distinct error payloads for the same HTTP status code, and there is currently no way to document them in the generated spec.Use Case
Consider a service where a single endpoint can return 400 Bad Request for two semantically different reasons, each with a different JSON payload structure:
The correct OpenAPI representation uses oneOf:
There is no existing annotation that carries this information into the generator.
The generator should: