{"record":{"id":"b1cf2ad363d806bb","repo":"getsops/sops","slug":"error-marshaling-timestamp-q-w","errorCode":null,"errorMessage":"Error marshaling timestamp %q: %w","messagePattern":"Error marshaling timestamp %q: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"aes/cipher.go","lineNumber":188,"sourceCode":"\t\tencryptedType = \"int\"\n\t\tplainBytes = []byte(strconv.Itoa(value))\n\tcase float64:\n\t\tencryptedType = \"float\"\n\t\t// The Python version encodes floats without padding 0s after the decimal point.\n\t\tplainBytes = []byte(strconv.FormatFloat(value, 'f', -1, 64))\n\tcase bool:\n\t\tencryptedType = \"bool\"\n\t\t// The Python version encodes booleans with Titlecase\n\t\tif value {\n\t\t\tplainBytes = []byte(\"True\")\n\t\t} else {\n\t\t\tplainBytes = []byte(\"False\")\n\t\t}\n\tcase time.Time:\n\t\tencryptedType = \"time\"\n\t\tplainBytes, err = value.MarshalText()\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"Error marshaling timestamp %q: %w\", value, err)\n\t\t}\n\tcase sops.Comment:\n\t\tencryptedType = \"comment\"\n\t\tplainBytes = []byte(value.Value)\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"Value to encrypt has unsupported type %T\", value)\n\t}\n\tout := gcm.Seal(nil, iv, plainBytes, []byte(additionalData))\n\treturn fmt.Sprintf(\"ENC[AES256_GCM,data:%s,iv:%s,tag:%s,type:%s]\",\n\t\tbase64.StdEncoding.EncodeToString(out[:len(out)-cryptoaes.BlockSize]),\n\t\tbase64.StdEncoding.EncodeToString(iv),\n\t\tbase64.StdEncoding.EncodeToString(out[len(out)-cryptoaes.BlockSize:]),\n\t\tencryptedType), nil\n}\n","sourceCodeStart":170,"sourceCodeEnd":203,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/aes/cipher.go#L170-L203","documentation":"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.","triggerScenarios":"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.","commonSituations":"Programmatically constructing sops trees with hand-built time.Time values containing NaN/extreme components; corrupted metadata parsed from a damaged file.","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."],"exampleFix":"// before\nvalue := time.Time{}\ncipher.Encrypt(value, key, ad)\n// after\nif value.IsZero() {\n    value = time.Now().UTC()\n}\ncipher.Encrypt(value, key, ad)","handlingStrategy":"validation","validationCode":"func validTime(t time.Time) bool {\n    return !t.IsZero() && t.Year() >= 0 && t.Year() <= 9999\n}","typeGuard":"if ts, ok := plaintext.(time.Time); ok && ts.IsZero() {\n    return fmt.Errorf(\"refusing to encrypt zero timestamp\")\n}","tryCatchPattern":"ciphertext, err := cipher.Encrypt(v, key, ad)\nif err != nil && strings.Contains(err.Error(), \"Error marshaling timestamp\") {\n    // rebuild the timestamp from the raw source value\n}","preventionTips":["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"],"tags":["sops","aes","encryption","timestamp","marshal"],"backgroundTag":"timestamp-marshal-failed","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}