grpc/grpc-go · error

ALTS: untrusted platform. ALTS is only supported on GCP

Error message

ALTS: untrusted platform. ALTS is only supported on GCP

What it means

ErrUntrustedPlatform (credentials/alts/alts.go:68-71) is returned from both altsTC.ClientHandshake and ServerHandshake when vmOnGCP is false. vmOnGCP is set once via googlecloud.OnGCE() (alts.go:155) — ALTS relies on a hypervisor-provided handshaker service whose trustworthiness is only guaranteed on GCE/GKE/Cloud Run.

Source

Thrown at credentials/alts/alts.go:71

	protocolVersionMinMajor = 2
	protocolVersionMinMinor = 1
)

var (
	vmOnGCP       bool
	once          sync.Once
	maxRPCVersion = &altspb.RpcProtocolVersions_Version{
		Major: protocolVersionMaxMajor,
		Minor: protocolVersionMaxMinor,
	}
	minRPCVersion = &altspb.RpcProtocolVersions_Version{
		Major: protocolVersionMinMajor,
		Minor: protocolVersionMinMinor,
	}
	// ErrUntrustedPlatform is returned from ClientHandshake and
	// ServerHandshake is running on a platform where the trustworthiness of
	// the handshaker service is not guaranteed.
	ErrUntrustedPlatform = errors.New("ALTS: untrusted platform. ALTS is only supported on GCP")
	logger               = grpclog.Component("alts")
)

// AuthInfo exposes security information from the ALTS handshake to the
// application. This interface is to be implemented by ALTS. Users should not
// need a brand new implementation of this interface. For situations like
// testing, any new implementation should embed this interface. This allows
// ALTS to add new methods to this interface.
type AuthInfo interface {
	// ApplicationProtocol returns application protocol negotiated for the
	// ALTS connection.
	ApplicationProtocol() string
	// RecordProtocol returns the record protocol negotiated for the ALTS
	// connection.
	RecordProtocol() string
	// SecurityLevel returns the security level of the created ALTS secure
	// channel.
	SecurityLevel() altspb.SecurityLevel

View on GitHub (pinned to 03255a9237)

Solutions

  1. Deploy the workload to GCP (GCE/GKE/Cloud Run/Cloud Functions) where the ALTS handshaker is available.
  2. Off-GCP, switch to TLS: grpc.WithTransportCredentials(credentials.NewTLS(tlsConf)) instead of ALTS.
  3. For local dev use insecure.NewCredentials() explicitly (never in production).
  4. In ALTS unit tests, set the unexported vmOnGCP via an internal test build or run the test on GCP.

Example fix

// before — ALTS off GCP
cc, _ := grpc.NewClient(target,
    grpc.WithTransportCredentials(alts.NewClientCreds(opts)))
// handshake error: ALTS: untrusted platform. ALTS is only supported on GCP

// after — TLS off GCP, ALTS only on GCP
var creds credentials.TransportCredentials
if onGCP {
    creds = alts.NewClientCreds(opts)
} else {
    creds = credentials.NewTLS(tlsConf)
}
cc, _ := grpc.NewClient(target, grpc.WithTransportCredentials(creds))
Defensive patterns

Strategy: fallback

Validate before calling

// Choose creds by environment so ALTS is only used on GCP
func pickCreds(onGCP bool) credentials.TransportCredentials {
    if onGCP {
        return alts.NewClientCreds(alts.DefaultClientOptions())
    }
    return credentials.NewTLS(&tls.Config{ServerName: server})
}

Try / catch

if errors.Is(err, alts.ErrUntrustedPlatform) {
    // not on GCP; fall back to TLS or fail explicitly
    creds = credentials.NewTLS(tlsConf)
}

Prevention

When it happens

Trigger: Code using alts.NewClientCreds()/alts.NewServerCreds() runs the handshake (clientconn.go dial → transport → ClientHandshake at alts.go:172-175, or server side at alts.go:218-221) on a host where googlecloud.OnGCE() returned false (not a GCE metadata server).

Common situations: Running ALTS locally or on AWS/on-prem; CI that is not on GCP; tests that forgot to force vmOnGCP=true (see alts_test.go:58-62); a container without metadata-server access.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/aa034b380980cf24. Report an issue: GitHub.