{"record":{"id":"6a85a21c73563084","repo":"windmill-labs/windmill","slug":"unexpected-tuple-byte","errorCode":null,"errorMessage":"unexpected tuple byte `{}`","messagePattern":"unexpected tuple byte `(.+?)`","errorType":"exception","errorClass":"ConversionError::Io (InvalidInput)","httpStatus":null,"severity":"error","filePath":"backend/windmill-trigger-postgres/src/replication_message.rs","lineNumber":375,"sourceCode":"            TYPE_BYTE => {\n                buf.read_u32::<BigEndian>()?;\n                buf.read_cstr()?;\n                buf.read_cstr()?;\n\n                LogicalReplicationMessage::Type\n            }\n            INSERT_BYTE => {\n                let transaction_id = match logical_replication_settings.streaming {\n                    true => Some(buf.read_i32::<BigEndian>()?),\n                    false => None,\n                };\n                let o_id = buf.read_u32::<BigEndian>()?;\n                let byte = buf.read_u8()?;\n\n                let tuple = match byte {\n                    TUPLE_NEW_BYTE => TupleData::parse(&mut buf)?,\n                    byte => {\n                        return Err(ConversionError::Io(io::Error::new(\n                            io::ErrorKind::InvalidInput,\n                            format!(\"unexpected tuple byte `{}`\", byte),\n                        )));\n                    }\n                };\n\n                LogicalReplicationMessage::Insert(InsertBody::new(transaction_id, o_id, tuple))\n            }\n            UPDATE_BYTE => {\n                let transaction_id = match logical_replication_settings.streaming {\n                    true => Some(buf.read_i32::<BigEndian>()?),\n                    false => None,\n                };\n                let o_id = buf.read_u32::<BigEndian>()?;\n                let byte = buf.read_u8()?;\n                let mut key_tuple = None;\n                let mut old_tuple = None;\n","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-trigger-postgres/src/replication_message.rs#L357-L393","documentation":"In a logical replication Update/Delete message, each tuple is prefixed by a byte indicating its kind ('N' for new, etc.). The parser only accepts the known tuple bytes and raises InvalidInput 'unexpected tuple byte `{}`' otherwise. Like the other replication byte errors, it usually signals a malformed or misaligned message stream.","triggerScenarios":"Parsing an Update/Delete replication message where the byte after the tuple's relation OID/column count is not the expected tuple marker (e.g. TUPLE_NEW_BYTE) — from stream misalignment, protocol mismatch, or corruption.","commonSituations":"Continuing to parse after an earlier partial/failed message; a Postgres version emitting tuple kinds the parser doesn't handle; corrupted replication connections.","solutions":["Restart replication / recreate the slot so parsing begins from a clean boundary.","Identify the offending byte to check whether it's a valid-but-unsupported tuple kind and extend the parser if so.","Confirm the pgoutput protocol options (proto version, publication) match the parser's expectations.","Check for an earlier desynchronizing parse error in the logs and fix that first."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match parse(msg_bytes) {\n    Err(ConversionError::Io(e)) if e.to_string().contains(\"unexpected tuple byte\") => {\n        tracing::warn!(\"unexpected tuple kind in update/delete message: {e}; resyncing slot\");\n    }\n    Ok(msg) => handle(msg),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Halt and resync the slot after the first parse error instead of continuing","Match pgoutput proto version options to the parser's supported versions","Log the offending byte to distinguish misalignment from genuinely new tuple kinds","Test replication triggers against your exact Postgres version before production"],"tags":["postgres","replication","protocol","tuple"],"backgroundTag":"unknown-protocol-message-type","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}