getsops/sops · error

Value to encrypt has unsupported type %T

Error message

Value to encrypt has unsupported type %T

What it means

Encrypt supports a fixed set of plaintext Go types (string, int/float, bool, time.Time, sops.Comment). Any other Go type reaches the default branch of the type switch and is rejected with this error naming the actual %T type. It protects the format: unencodable values would silently corrupt the document.

Source

Thrown at aes/cipher.go:194

	case bool:
		encryptedType = "bool"
		// The Python version encodes booleans with Titlecase
		if value {
			plainBytes = []byte("True")
		} else {
			plainBytes = []byte("False")
		}
	case time.Time:
		encryptedType = "time"
		plainBytes, err = value.MarshalText()
		if err != nil {
			return "", fmt.Errorf("Error marshaling timestamp %q: %w", value, err)
		}
	case sops.Comment:
		encryptedType = "comment"
		plainBytes = []byte(value.Value)
	default:
		return "", fmt.Errorf("Value to encrypt has unsupported type %T", value)
	}
	out := gcm.Seal(nil, iv, plainBytes, []byte(additionalData))
	return fmt.Sprintf("ENC[AES256_GCM,data:%s,iv:%s,tag:%s,type:%s]",
		base64.StdEncoding.EncodeToString(out[:len(out)-cryptoaes.BlockSize]),
		base64.StdEncoding.EncodeToString(iv),
		base64.StdEncoding.EncodeToString(out[len(out)-cryptoaes.BlockSize:]),
		encryptedType), nil
}

View on GitHub (pinned to 13442bb981)

Solutions

  1. Convert the value to a scalar (string, int, float, bool, time.Time) before encrypting.
  2. For complex values, serialize to a string (YAML/JSON) and encrypt the string.
  3. Add a case to the type switch in Encrypt if you fork and need a new supported type.

Example fix

// before
cipher.Encrypt(map[string]interface{}{"a": 1}, key, ad)
// after
cipher.Encrypt(fmt.Sprintf("a: 1", ), key, ad) // or encrypt a scalar only
Defensive patterns

Strategy: type-guard

Validate before calling

func encodable(v interface{}) bool {
    switch v.(type) {
    case string, int, int64, float64, bool, time.Time, sops.Comment:
        return true
    }
    return false
}

Type guard

if !encodable(value) {
    value = fmt.Sprintf("%v", value) // coerce to string first
}

Try / catch

ciphertext, err := cipher.Encrypt(v, key, ad)
if err != nil && strings.Contains(err.Error(), "unsupported type") {
    return cipher.Encrypt(fmt.Sprintf("%v", v), key, ad)
}

Prevention

When it happens

Trigger: Passing a value of an unsupported type to Cipher.Encrypt — e.g. a map, slice, nil pointer, or custom struct inserted into a sops TreeBranch instead of a scalar.

Common situations: Programmatic use of the sops API where developers insert arbitrary Go objects into the tree; reflection-based tooling that forwards raw parsed YAML/JSON nodes (maps/slices) instead of leaves.

Related errors


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