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

  1. Validate the time.Time (e.g. value.IsZero(), finite year) before passing it to Encrypt.
  2. Reconstruct the timestamp by re-parsing the source value with time.Parse(time.RFC3339, ...).
  3. 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

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


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