xai-org/x-algorithm · error · IllegalArgumentException

Pairs are not supported in strato JSON

Error message

Pairs are not supported in strato JSON

What it means

The map serializer's toStratoJson override throws IllegalArgumentException because Pair (the key/value pair of a map entry, per the visible genScript usage of pair.getSecond()) has no representation in strato JSON. When a value containing pairs is converted to the strato JSON format, serialization deliberately fails rather than emitting malformed JSON.

Source

Thrown at botmaker/src/java/com/twitter/botmaker/compiler/Serializer.java:1313

      @Override
      protected Pair deserialize(TProtocol prot) throws Exception {

        return Pair.of(
            keyType.serializer.deserialize(prot, true),
            valType.serializer.deserialize(prot, true));
      }

      @Override
      protected void toScript(GenScript script, Pair pair) throws Exception {
        keyType.serializer.genScript(script, pair.getFirst());
        script.builder.append(": ");
        valType.serializer.genScript(script, pair.getSecond());
      }

      @Override
      protected void toStratoJson(GenScript script, Pair pair) {
        throw new IllegalArgumentException("Pairs are not supported in strato JSON");
      }
    };
  }

  public static Serializer<Tuple> tupleOf(Type... typeParams) {
    return new Serializer<Tuple>() {

      @Override
      public void computeFingerprint(Hasher hasher, Tuple tuple) throws Exception {
        for (Type type : typeParams) {
          type.computerFingerprint(hasher);
        }

        for (int index = 0; index < tuple.size(); index++) {
          hasher.putInt(index);
          if (tuple.get(index) != null) {
            typeParams[index].serializer.computeFingerprint(hasher, tuple.get(index));
          }

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Restructure the data so pairs are represented as a thrift struct or a list of key/value structs, which have strato JSON support via thriftStructOf.
  2. Avoid calling genStratoJson on serializers built with pairOf; use genScript (fingerprint path) for those values.
  3. If strato output is required, change the underlying schema to use a struct-tuple or named struct instead of Pair.

Example fix

// before
Serializer<Pair<A,B>> s = Serializer.pairOf(aS, bS);
s.genStratoJson(script, pair); // throws Pairs are not supported in strato JSON

// after
MyPairStruct struct = MyPairStruct(pair.getFirst(), pair.getSecond());
Serializer.thriftStructOf(MyPairStruct.class).genStratoJson(script, struct);
Defensive patterns

Strategy: validation

Validate before calling

if (typeIncludesPair(featureType)) {
  throw new IllegalArgumentException(featureName + " uses Pair, not strato-JSON serializable");
}

Type guard

static boolean stratoSerializableType(Serializer<?> s) {
  return !isPairSerializer(s); // track serializer kind when constructed
}

Try / catch

catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Pairs are not supported")) {
    // use genScript fingerprint path instead
  } else throw e;
}

Prevention

When it happens

Trigger: Constructing a Serializer via the pair/map factory (Serializer code path around line 1313) and then calling genStratoJson on data containing Pair values; e.g. serializing a feature whose type includes a map/pair type to strato JSON.

Common situations: Defining a botmaker rule field or constant with a pair/map type and then enabling strato JSON export/serving for it; reusing a serializer built for fingerprinting in a strato JSON context.

Related errors


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