golang/go · error

SWIG file must not use prefix 'cgo'

Error message

SWIG file must not use prefix 'cgo'

What it means

Thrown by swigOne in cmd/go/internal/work before invoking swig, when the input .swig file's basename begins with "cgo" (e.g. cgo.swig, cgomodule.swig). The cgo tool runs after SWIG and writes intermediate files named cgo_*; a SWIG input with that prefix collides with cgo's output naming scheme, causing silent file overwrites and broken builds. The go command rejects it up front.

Solutions

  1. Rename the .swig file so its basename does not start with "cgo" — e.g. wrapper.swig, binding.swig, or <package>.swig.
  2. Update any build scripts, Makefiles, or //go:generate directives that reference the old filename.
  3. Add a pre-commit hook or CI check that flags *.swig files beginning with "cgo".

Example fix

# before
$ ls
main.go  cgo.swig
$ go build ./...
# -> SWIG file must not use prefix 'cgo'

# after
$ mv cgo.swig wrapper.swig
$ go build ./...
Defensive patterns

Strategy: validation

Validate before calling

func validateSwigFilenames(files []string) error {
    for _, f := range files {
        if strings.HasPrefix(filepath.Base(f), "cgo") {
            return fmt.Errorf("SWIG file %q must not begin with 'cgo' — rename it", f)
        }
    }
    return nil
}

Type guard

func swigNameOK(name string) bool { return !strings.HasPrefix(filepath.Base(name), "cgo") }

Prevention

When it happens

Trigger: Naming a SWIG interface file cgo.swig, cgotypes.swig, or any file whose name starts with the three letters "cgo". Renaming an existing .swig file to add a cgo prefix for organizational reasons.

Common situations: Teams that prefix all cgo-related files with "cgo" for sorting. Code generators that emit filename prefixes based on package features. Copy-paste of SWIG examples that happened to use the cgo prefix.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/b1b9634fca888051. Report an issue: GitHub.

Appendix: source

Thrown at src/cmd/go/internal/work/exec.go:3764

	if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, nil, "", false, "", "", srcs); e != nil {
		return "32", nil
	}
	return "64", nil
}

// Determine the size of int on the target system for the -intgosize option
// of swig >= 2.0.9.
func (b *Builder) swigIntSize(objdir string) (intsize string, err error) {
	swigIntSizeOnce.Do(func() {
		swigIntSize, swigIntSizeError = b.swigDoIntSize(objdir)
	})
	return swigIntSize, swigIntSizeError
}

// Run SWIG on one SWIG input file.
func (b *Builder) swigOne(a *Action, file, objdir string, pcCFLAGS []string, cxx bool, intgosize string) error {
	if strings.HasPrefix(file, "cgo") {
		return errors.New("SWIG file must not use prefix 'cgo'")
	}

	p := a.Package
	sh := b.Shell(a)

	cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _, err := b.CFlags(p)
	if err != nil {
		return err
	}

	var cflags []string
	if cxx {
		cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
	} else {
		cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
	}

	base := swigBase(file, cxx)

View on GitHub (pinned to b6b368adc5)