golang/go · error

cipher: the nonce can't have zero length

Error message

cipher: the nonce can't have zero length

What it means

newGCMFallback requires nonceSize > 0 because a zero-length nonce breaks GCM's counter initialization (the J0 computation assumes at least one block worth of nonce processing). The check fires after the tag-size check and before the gcmAble fast-path.

Source

Thrown at src/crypto/cipher/gcm.go:208

	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    Block
	nonceSize int
	tagSize   int
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Pass a positive nonce length; 12 (gcmStandardNonceSize) is strongly recommended.
  2. Default to cipher.NewGCM(block) which uses the standard 12-byte nonce and avoids the question entirely.
  3. Validate config-driven nonce sizes at load time: reject zero and negative values before they reach the constructor.

Example fix

// before
a, err := cipher.NewGCMWithNonceSize(block, cfg.NonceSize) // cfg.NonceSize == 0
// "the nonce can't have zero length"

// after: explicit, standard nonce size
a, err := cipher.NewGCM(block) // 12-byte nonce
// or
if cfg.NonceSize <= 0 { cfg.NonceSize = 12 }
a, err := cipher.NewGCMWithNonceSize(block, cfg.NonceSize)
Defensive patterns

Strategy: validation

Validate before calling

func newAEADSizedNonce(block cipher.Block, size int) (cipher.AEAD, error) {
    if size <= 0 {
        return nil, errors.New("nonce size must be positive")
    }
    return cipher.NewGCMWithNonceSize(block, size)
}

Try / catch

a, err := cipher.NewGCMWithNonceSize(block, size)
if err != nil && strings.Contains(err.Error(), "nonce can't have zero length") {
    // Default to standard 12-byte nonce.
    a, err = cipher.NewGCM(block)
}

Prevention

When it happens

Trigger: Calling cipher.NewGCMWithNonceSize(block, 0) — typically because the size argument was an uninitialized int (zero value), or because the caller derived nonceSize from a misconfigured constant.

Common situations: Reading nonceSize from a config struct whose field was never populated; passing `0` as a sentinel that the API does not honor; refactoring that left a temporary placeholder in place.

Related errors


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