{"record":{"id":"727bfbdafeff0ae1","repo":"nats-io/nats-server","slug":"failed-to-parse-message-ttl-w","errorCode":null,"errorMessage":"failed to parse message TTL: %w","messagePattern":"failed to parse message TTL: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/stream_backup.go","lineNumber":528,"sourceCode":"\t\t\treturn nil, fmt.Errorf(\"failed to read message sequence %d: unexpected payload size\", seq)\n\t\t}\n\t\tsubj := hdr.Name\n\t\tmhdr := buf[:hdr.HeaderSize]\n\t\tmsg := buf[hdr.HeaderSize : hdr.HeaderSize+hdr.PayloadSize]\n\t\tif seq <= lseq {\n\t\t\treturn nil, fmt.Errorf(\"message sequence %d out of order\", seq)\n\t\t}\n\t\t// We could have deleted messages since the last message we stored, if so\n\t\t// we should work out what the gap is and skip those sequences.\n\t\tif gap := seq - lseq - 1; gap > 0 {\n\t\t\tif err := store.SkipMsgs(lseq+1, gap); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to process gap: %w\", err)\n\t\t\t}\n\t\t}\n\t\tlseq = seq\n\t\tttl, err := getMessageTTL(mhdr)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse message TTL: %w\", err)\n\t\t}\n\t\thdrTime := time.Unix(0, hdr.Timestamp)\n\t\tif ttl > 0 && time.Now().After(hdrTime.Add(time.Duration(ttl)*time.Second)) {\n\t\t\t// If the TTL has exceeded then there isn't much point in storing the message,\n\t\t\t// but we still need to preserve the sequence.\n\t\t\tif err := store.SkipMsgs(seq, 1); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to process expired message sequence %d: %w\", seq, err)\n\t\t\t}\n\t\t\treleaseRestoreBytes(storedSize)\n\t\t\tcontinue\n\t\t}\n\t\tif err = store.StoreRawMsg(subj, mhdr, msg, seq, hdr.Timestamp, ttl, false); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to store message sequence %d: %w\", seq, err)\n\t\t}\n\t\treleaseRestoreBytes(storedSize)\n\t}\n\n\tif !eob {","sourceCodeStart":510,"sourceCodeEnd":546,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream_backup.go#L510-L546","documentation":"Each backed-up message carries a subject header from which an optional per-message TTL is extracted via getMessageTTL. This error is returned when that TTL header cannot be parsed, so the restore cannot decide whether the message is expired. It indicates malformed message headers in the backup.","triggerScenarios":"getMessageTTL(mhdr) fails to parse the TTL value embedded in the message's header bytes during RestoreStreamV2; caused by malformed or non-numeric NATS-Message-TTL header data, corrupted header bytes, or headers written by incompatible tooling.","commonSituations":"Backups whose message headers were hand-edited or produced by third-party tools emitting invalid TTL header values, or corrupted archive bytes in the header region.","solutions":["Re-create the backup from the source stream so headers are re-serialized correctly","Validate message headers on the source stream (fix or clear bad per-message TTLs before backing up)","Ensure the same/compatible nats-server version is used for backup and restore","If corruption is suspected, restore from an earlier known-good backup"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// on the source stream, validate per-message TTL headers before backup\nmsgs, _ := sub.Fetch(n)\nfor _, m := range msgs {\n    if t := m.Header.Get(\"NATS-Message-TTL\"); t != \"\" {\n        if _, err := strconv.Atoi(t); err != nil { return fmt.Errorf(\"invalid TTL header %q\", t) }\n    }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to parse message TTL\") {\n    // backup headers are malformed; re-create backup from source\n}","preventionTips":["Fix invalid per-message TTL headers on the source before backing up","Don't hand-edit message headers inside backups","Use compatible server versions for header serialization","Validate message headers before storing to streams"],"tags":["jetstream","restore","headers","ttl"],"backgroundTag":"malformed-message-header","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}