getsops/sops · error

decryption response missing plaintext

Error message

decryption response missing plaintext

What it means

If DecryptData returns successfully but response.PlainText is nil, DecryptContext (hckms/keysource.go:225) throws this error. Like the ciphertext case, it indicates an HTTP-success response that lacks the expected plaintext field, so the data key cannot be recovered.

Source

Thrown at hckms/keysource.go:225

	decryptAlgorithm := model.GetDecryptDataRequestBodyEncryptionAlgorithmEnum().SYMMETRIC_DEFAULT

	request := &model.DecryptDataRequest{
		Body: &model.DecryptDataRequestBody{
			CipherText:          key.EncryptedKey,
			EncryptionAlgorithm: &decryptAlgorithm,
			KeyId:               &key.KeyUUID,
		},
	}

	response, err := client.DecryptData(request)
	if err != nil {
		log.WithField("keyID", key.KeyID).Info("Decryption failed")
		return nil, fmt.Errorf("failed to decrypt sops data key with HuaweiCloud KMS: %w", err)
	}

	if response.PlainText == nil {
		return nil, fmt.Errorf("decryption response missing plaintext")
	}
	decrypted, err := base64.StdEncoding.DecodeString(*response.PlainText)
	if err != nil {
		log.WithField("keyID", key.KeyID).Info("Decryption failed")
		return nil, fmt.Errorf("failed to base64 decode decrypted data key: %w", err)
	}

	log.WithField("keyID", key.KeyID).Info("Decryption succeeded")
	return decrypted, nil
}

// NeedsRotation returns whether the data key needs to be rotated or not.
func (key *MasterKey) NeedsRotation() bool {
	return time.Since(key.CreationDate) > hckmsTTL
}

// ToString converts the key to a string representation.
func (key *MasterKey) ToString() string {

View on GitHub (pinned to 13442bb981)

Solutions

  1. Dump the raw HTTP response of the DecryptData call to see what the server returned
  2. Check for proxies/gateways altering the response (bypass HTTP_PROXY)
  3. Pin/upgrade the huaweicloud-sdk-go-v3 version to one matching your KMS API
  4. Retry the decrypt; contact HuaweiCloud support if reproducible
Defensive patterns

Strategy: retry

Type guard

func validDecryptResponse(r *model.DecryptDataResponse) bool {
    return r != nil && r.PlainText != nil && *r.PlainText != ""
}

Try / catch

dataKey, err := key.DecryptContext(ctx)
if err != nil && strings.Contains(err.Error(), "missing plaintext") {
    // retry once; if persistent, log raw response and report to HuaweiCloud support
    return err
}

Prevention

When it happens

Trigger: client.DecryptData returns err == nil with a model.DecryptDataResponse whose PlainText pointer is nil — empty/anomalous 2xx response, or an intermediary returning 200 with an unexpected body.

Common situations: Proxy/gateway tampering with responses; SDK response deserialization issues with a newer/older SDK version against the live API; HuaweiCloud service anomaly.

Related errors


AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01). Data as JSON: /api/errors/70b3f7cb2df29636. Report an issue: GitHub.