xai-org/x-algorithm · error

Not implemented: to_thrift for SafetyResult

Error message

Not implemented: to_thrift for SafetyResult

What it means

SafetyResult implements only the Thrift decode half of MValCodec; to_thrift panics because serialization was never needed for this type. The panic documents an intentional hole in the codec implementation rather than a runtime condition.

Source

Thrown at visibility-filtering-client/models.rs:192

                        32 => SafetyResultReason::GoreAndViolenceHighPrecision,
                        _ => SafetyResultReason::Episodic,
                    });
                }
                Some(2) => {
                    action = Action::from_thrift(proto);
                }
                _ => {
                    proto.skip(field.field_type).unwrap();
                }
            }
            proto.read_field_end().unwrap();
        }
        proto.read_struct_end().unwrap();
        SafetyResult { reason, action }
    }

    fn to_thrift(&self, _proto: &mut dyn TOutputProtocol) {
        panic!("Not implemented: to_thrift for SafetyResult")
    }
}

impl MValCodec for Action {
    fn thrift_type() -> TType {
        TType::Struct
    }

    fn from_thrift(proto: &mut dyn TInputProtocol) -> Self {
        proto.read_struct_begin().unwrap();
        let mut result = Action::NotEvaluated;
        loop {
            let field = proto.read_field_begin().unwrap();
            if field.field_type == TType::Stop {
                break;
            }
            match field.id {
                Some(1) => {

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Avoid encoding SafetyResult; consume it via from_thrift only.
  2. Implement to_thrift mirroring the decoder: write 'reason' and 'action' fields with the same field ids/types the reader expects.
  3. Serialize an equivalent protobuf type if one exists instead of the Thrift codec.

Example fix

// before
fn to_thrift(&self, _proto: &mut dyn TOutputProtocol) {
    panic!("Not implemented: to_thrift for SafetyResult")
}

// after: mirror the reader's field ids (1: reason, 2: action)
fn to_thrift(&self, proto: &mut dyn TOutputProtocol) {
    proto.write_struct_begin(&TStructIdentifier::new("SafetyResult")).unwrap();
    self.reason.write_field(proto, 1);
    self.action.write_field(proto, 2);
    proto.write_field_stop().unwrap();
    proto.write_struct_end().unwrap();
}
Defensive patterns

Strategy: type-guard

Type guard

trait WriteCodec { fn to_thrift(&self, p: &mut dyn TOutputProtocol); }
fn encode<T: WriteCodec>(v: &T, p: &mut dyn TOutputProtocol) { v.to_thrift(p); }
// SafetyResult: encode via this fn is a compile error until implemented

Try / catch

let r = std::panic::catch_unwind(|| sr.to_thrift(proto));
if r.is_err() { /* log and serialize the protobuf equivalent instead */ }

Prevention

When it happens

Trigger: Serializing a SafetyResult (reason + action fields) to Thrift: writing it to a log/mval sink, sending it over a Thrift service, or a generic encode path / round-trip test that invokes to_thrift.

Common situations: New feature code starts emitting SafetyResult over the wire or into storage; generic codec utilities that encode every MValCodec type; test harnesses that verify symmetry between from_thrift and to_thrift.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/7943a9e6fa0b60fc. Report an issue: GitHub.