getsops/sops · error
Error marshaling timestamp %q: %w
Error message
Error marshaling timestamp %q: %w
What it means
When the plaintext value is a time.Time, Encrypt serializes it with MarshalText before sealing. If the timestamp cannot be marshaled (only possible for out-of-range or corrupt time.Time values such as year > 9999 in some formats), this error wraps both the value and the underlying failure. It is one of the typed branches of the plaintext switch.
Source
Thrown at aes/cipher.go:188
encryptedType = "int"
plainBytes = []byte(strconv.Itoa(value))
case float64:
encryptedType = "float"
// The Python version encodes floats without padding 0s after the decimal point.
plainBytes = []byte(strconv.FormatFloat(value, 'f', -1, 64))
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
- Validate the time.Time (e.g. value.IsZero(), finite year) before passing it to Encrypt.
- Reconstruct the timestamp by re-parsing the source value with time.Parse(time.RFC3339, ...).
- If the value came from a corrupted file, restore the file or re-enter the timestamp.
Example fix
// before
value := time.Time{}
cipher.Encrypt(value, key, ad)
// after
if value.IsZero() {
value = time.Now().UTC()
}
cipher.Encrypt(value, key, ad) Defensive patterns
Strategy: validation
Validate before calling
func validTime(t time.Time) bool {
return !t.IsZero() && t.Year() >= 0 && t.Year() <= 9999
} Type guard
if ts, ok := plaintext.(time.Time); ok && ts.IsZero() {
return fmt.Errorf("refusing to encrypt zero timestamp")
} Try / catch
ciphertext, err := cipher.Encrypt(v, key, ad)
if err != nil && strings.Contains(err.Error(), "Error marshaling timestamp") {
// rebuild the timestamp from the raw source value
} Prevention
- Always construct timestamps with time.Parse(time.RFC3339, ...)
- Reject zero/NaN time values before inserting into the sops tree
- Round-trip test timestamps before encrypting
When it happens
Trigger: Calling Cipher.Encrypt with a time.Time value whose MarshalText fails — e.g. a zero-initialized or malformed time with out-of-range fields produced by a corrupted tree or bad deserialization.
Common situations: Programmatically constructing sops trees with hand-built time.Time values containing NaN/extreme components; corrupted metadata parsed from a damaged file.
Related errors
- Could not initialize AES GCM encryption cipher: %s
- Could not generate random bytes for IV: %s
- Could not create GCM: %s
- Value to encrypt has unsupported type %T
- Unknown datatype: %s
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/b1cf2ad363d806bb.
Report an issue: GitHub.