golang/go · error
cipher: incorrect tag size given to GCM
Error message
cipher: incorrect tag size given to GCM
What it means
newGCMFallback (the generic GCM implementation used when the cipher is not AES) validates that tagSize is within [gcmMinimumTagSize=12, gcmBlockSize=16]. Values outside this range — including the natural-seeming 8 or 32 — are rejected because NIST SP 800-38D only permits final-authentication-tag lengths of 128, 120, 112, 104, 96, 64, and 32 bits, and the Go generic path restricts further to the 96..128-bit subset.
Source
Thrown at src/crypto/cipher/gcm.go:205
}
_, err := g.GCM.Open(out[:0], nonce, ciphertext, additionalData)
if err != nil {
return nil, err
}
return ret, nil
}
// gcmAble is an interface implemented by ciphers that have a specific optimized
// implementation of GCM. crypto/aes doesn't use this anymore, and we'd like to
// eventually remove it.
type gcmAble interface {
NewGCM(nonceSize, tagSize int) (AEAD, error)
}
func newGCMFallback(cipher Block, nonceSize, tagSize int) (AEAD, error) {
if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize {
return nil, errors.New("cipher: incorrect tag size given to GCM")
}
if nonceSize <= 0 {
return nil, errors.New("cipher: the nonce can't have zero length")
}
if cipher, ok := cipher.(gcmAble); ok {
return cipher.NewGCM(nonceSize, tagSize)
}
if cipher.BlockSize() != gcmBlockSize {
return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
}
return &gcmFallback{cipher: cipher, nonceSize: nonceSize, tagSize: tagSize}, nil
}
// gcmFallback is only used for non-AES ciphers, which regrettably we
// theoretically support. It's a copy of the generic implementation from
// crypto/internal/fips140/aes/gcm/gcm_generic.go, refer to that file for more details.
type gcmFallback struct {
cipher BlockView on GitHub (pinned to b6b368adc5)
Solutions
- Use one of {12, 13, 14, 15, 16} for tagSize.
- Default to NewGCM (tag size 16) unless you have a measured bandwidth constraint; 12 bytes is the minimum.
- If you truly need an 8-byte tag, you are outside GCM's allowed set — use a separate MAC construction.
Example fix
// before a, err := cipher.NewGCMWithTagSize(block, 8) // "incorrect tag size" // after a, err := cipher.NewGCMWithTagSize(block, 12) // minimum allowed
Defensive patterns
Strategy: validation
Validate before calling
func validGCMTagSize(n int) error {
const (
gcmMinimumTagSize = 12
gcmBlockSize = 16
)
if n < gcmMinimumTagSize || n > gcmBlockSize {
return fmt.Errorf("tag size %d outside [%d, %d]", n, gcmMinimumTagSize, gcmBlockSize)
}
return nil
} Try / catch
a, err := cipher.NewGCMWithTagSize(block, tag)
if err != nil && strings.Contains(err.Error(), "incorrect tag size") {
// Fall back to the standard 16-byte tag.
a, err = cipher.NewGCM(block)
} Prevention
- Default to NewGCM (16-byte tag) unless bandwidth is measured-critical.
- Validate config-driven tag sizes at load time against {12..16}.
- Document that 8-byte tags are not supported by Go's GCM.
When it happens
Trigger: Calling cipher.NewGCMWithTagSize(block, tagSize) with tagSize < 12 or > 16, where block is not *aes.Block (so newGCMFallback runs). On AES the same range is enforced inside gcm.New and surfaces a similar error.
Common situations: Trying to shorten the tag to 8 bytes for bandwidth, or extending it to 32 bytes for stronger (but unsupported) authentication; misreading the spec and assuming any positive length works.
Related errors
- cipher: the nonce can't have zero length
- crypto/cipher: use of GCM with arbitrary IVs is not allowed
- crypto/cipher: use of GCM with non-AES ciphers is not allowe
- cipher: NewGCMWithRandomNonce requires aes.Block
- cipher: NewGCM requires 128-bit block cipher
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/57d41abfdeb71d59.
Report an issue: GitHub.