golang/go · error

FIPS 140-3 mode is incompatible with the purego build tag

Error message

FIPS 140-3 mode is incompatible with the purego build tag

What it means

Returned by fips140.Supported() when the purego build tag is active. FIPS 140-3 validation only covers the assembly-backed implementations; purego replaces too much crypto code with Go-level implementations, invalidating the validation boundary.

Source

Thrown at src/crypto/internal/fips140/fips140.go:38

	case "on", "only":
		Enabled = true
	case "debug":
		Enabled = true
		debug = true
	case "off", "":
	default:
		panic("fips140: unknown GODEBUG setting fips140=" + v)
	}
}

// Supported returns an error if FIPS 140-3 mode can't be enabled.
func Supported() error {
	// Keep this in sync with fipsSupported in cmd/dist/test.go.

	// The purego tag changes too much of the implementation to claim the
	// validation still applies.
	if puregoEnabled {
		return errors.New("FIPS 140-3 mode is incompatible with the purego build tag")
	}

	// ASAN disapproves of reading swaths of global memory in fips140/check.
	// One option would be to expose runtime.asanunpoison through
	// crypto/internal/fips140deps and then call it to unpoison the range
	// before reading it, but it is unclear whether that would then cause
	// false negatives. For now, FIPS+ASAN doesn't need to work.
	if asanEnabled {
		return errors.New("FIPS 140-3 mode is incompatible with ASAN")
	}

	// See EnableFIPS in cmd/internal/obj/fips.go for commentary.
	// Also, js/wasm and windows/386 don't have good enough timers
	// for the CPU jitter entropy source.
	switch {
	case runtime.GOARCH == "wasm",
		runtime.GOOS == "windows" && runtime.GOARCH == "386",
		runtime.GOOS == "openbsd", // due to -fexecute-only, see #70880

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Drop the purego build tag for the FIPS build target.
  2. Use a supported architecture (amd64, arm64, s390x) where assembly backends exist and purego is not required.
  3. If you need purego for portability, do not also enable FIPS mode — pick one.
  4. Audit GOFLAGS, makefiles, and Dockerfiles for stray -tags=purego.

Example fix

# before
GOFLAGS="-tags=purego" GOFIPS140=1 go build ./...

# after
GOFIPS140=1 go build ./...
Defensive patterns

Strategy: validation

Validate before calling

if err := fips140.Supported(); err != nil {
    if strings.Contains(err.Error(), "purego") {
        log.Fatal("FIPS mode requires assembly backends; drop the purego build tag")
    }
    log.Fatalf("FIPS unsupported: %v", err)
}

Try / catch

if err := fips140.Supported(); err != nil {
    // surface at deploy time before serving traffic
    return fmt.Errorf("refusing to start: FIPS mode unavailable: %w", err)
}

Prevention

When it happens

Trigger: Building with -tags purego (or GOFLAGS containing it) and then calling fips140.Supported() or attempting to enable FIPS mode via GOFIPS140=1.

Common situations: Cross-compiling without assembly support; CI pipelines that add purego globally; tooling that injects purego for portability on unsupported architectures.

Related errors


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