Skip to content

openapiv3: same-named services in different packages silently overwrite each other's spec file #243

Description

@hishamank

Summary

protoc-gen-openapiv3 names its per-service output file from the service name only, unqualified by proto package. Two services with the same name in different packages therefore map to the same filename, and one spec is silently dropped — the affected service ends up with no OpenAPI documentation at all.

Reproduction

Two services sharing a name in different packages:

// anghamna/b2b/v1/service.proto
package anghamna.b2b.v1;
service VideoStreamingService {
  option (sebuf.http.service_config) = { base_path: "/api/b2b/v1" };
  rpc GetLiveChannelsWithStreams(...) returns (...) {
    option (sebuf.http.config) = { path: "/get-live-channels-with-streams" };
  }
}
// anghamna/videostreaming/v1/service.proto
package anghamna.videostreaming.v1;
service VideoStreamingService {
  option (sebuf.http.service_config) = { base_path: "/api/video-streaming/v1" };
  rpc GetLiveStreams(...) returns (...) { option (sebuf.http.config) = { path: "/get-live-streams" }; }
  rpc GetVodStreams(...) returns (...) { option (sebuf.http.config) = { path: "/get-vod-streams" }; }
}

Both resolve to VideoStreamingService.openapi.yaml.

Observed

buf generate warns and continues:

duplicate generated file name "VideoStreamingService.openapi.yaml". Generation will
continue without error here and drop the second occurrence of this file, but please
raise an issue with the maintainer of the plugin.

In a real repo with 15 services this produced 14 spec files. The surviving VideoStreamingService.openapi.yaml contained only the b2b paths (/api/b2b/v1/get-live-channels-with-streams); anghamna.videostreaming.v1.VideoStreamingService and its two RPCs were absent from the generated docs entirely.

Which service wins depends on generation order, so this can also flip silently between runs or protoc versions.

Expected

Either:

  • Qualify the filename when a collision would occur (or always), e.g. anghamna.b2b.v1.VideoStreamingService.openapi.yaml / a package-derived path — so both specs are emitted; or
  • Fail loudly at generation time with a clear message naming both services, matching how the toolkit already fails loud on other unrepresentable inputs (ValidateFileURLParams, CheckESMessageAnnotations, checkNoEnumParamsES).

Silently emitting an incomplete spec set is the worst of the three outcomes — consumers get a spec that looks complete.

Note

Bundle mode already handles the analogous collision for schemas by proto-package-qualifying names (sebuf.test.Usersebuf_test_User, per the "OpenAPI Bundle Mode" docs). The gap is only in per-service file naming.

Environment

Verified on main @ d3bcc2a (latest at time of writing) — 15 services in the
protos, 14 spec files emitted, same duplicate generated file name warning, and the
surviving VideoStreamingService.openapi.yaml contains only the b2b paths.

  • sebuf main @ d3bcc2a
  • buf 1.57.2

It also reproduces on the older v0.17.0 pin, which is only meant to say the bug is
long-standing rather than a recent regression — the report itself is against main.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions