Skip to content
This repository was archived by the owner on May 27, 2026. It is now read-only.

Resolve import cycle when enum is in same Go package#1378

Merged
rodaine merged 1 commit into
bufbuild:mainfrom
TravelThePath:main
May 27, 2026
Merged

Resolve import cycle when enum is in same Go package#1378
rodaine merged 1 commit into
bufbuild:mainfrom
TravelThePath:main

Conversation

@TravelThePath

Copy link
Copy Markdown
Contributor

Summary

Fix self-import cycle in generated *.pb.validate.go files when proto files within the same Go package reference each other's enum types.

Problem

When proto file A imports proto file B, and both files share the same go_package but have different proto package names, the generated A.pb.validate.go file imports its own Go package, creating an import cycle that breaks go build.

Example:

  • entity_admin.proto (proto package jasper.admin.entity.v0, go_package admin/pb)
  • document_admin.proto (proto package jasper.admin.document.v0, go_package admin/pb)

When entity_admin.proto uses DocumentVisibility (defined in document_admin.proto) in a field with validation rules, the generated code produces:

package pb  // file is IN admin/pb

import (
    pb "github.com/example/service/admin/pb"  // imports ITSELF → cycle
)

var (
    _ = pb.DocumentVisibility(0)  // dead assignment requiring the self-import
)

This pattern is common in codebases that vendor proto files from other services and set go_package to the local service path.

Root Cause

The externalEnums function in templates/goshared/register.go determines whether an enum needs an external import by comparing proto package names:

if en != nil && en.File().Package().ProtoName() != msg.File().Package().ProtoName() {

This is incorrect because two proto files can have different proto package names but share the same go_package option, placing them in the same Go package. The comparison should use Go import paths instead.

This regression was introduced when the original dual check (ProtoName + PackageName) was simplified to only ProtoName during the enum package collision fix.

Fix

Changed the comparison from proto package name to Go import path using fns.ImportPath(), which is the same API that protoc-gen-star's own importableTypeName function (in type_name.go:38) uses for the identical purpose:

fileImportPath := fns.ImportPath(file)

if en != nil && fns.ImportPath(en) != fileImportPath {

Testing

  • Verified against 6 Go microservices that exhibited this bug — all now build cleanly
  • go build ./... passes on the protoc-gen-validate repo itself
  • go vet ./... passes

Related Issues

🤖 Generated with Claude Code

The externalEnums function compared proto package names to determine
if an enum needed an external import. This is incorrect because two
proto files can have different proto package names but share the same
go_package option, placing them in the same Go package. When this
happens, the generated .pb.validate.go file imports its own Go
package, creating an import cycle that breaks go build.

Changed the comparison from proto package name to Go import path
using fns.ImportPath(), which is the same API that protoc-gen-star's
own importableTypeName function uses for the identical purpose.

Fixes bufbuild#585

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Mar 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@rodaine rodaine closed this May 27, 2026
@rodaine rodaine reopened this May 27, 2026
@rodaine rodaine changed the title fix(go): resolve import cycle when enum is in same Go package Resolve import cycle when enum is in same Go package May 27, 2026

@rodaine rodaine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch!

@rodaine rodaine merged commit 414042a into bufbuild:main May 27, 2026
6 of 8 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants