xai-org/x-algorithm · error · IllegalArgumentException

Tuples are not supported in strato JSON

Error message

Tuples are not supported in strato JSON

What it means

The tuple serializer supports fingerprint generation (toScript writes parenthesized elements) but its toStratoJson override unconditionally throws IllegalArgumentException because the Tuple type has no strato JSON encoding. Any attempt to convert a Tuple value into strato JSON fails immediately.

Source

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

      protected void toScript(GenScript script, Tuple tuple) throws Exception {
        script.builder.append("Tuple(");
        script.level++;

        for (int index = 0; index < tuple.size(); index++) {
          if (index > 0) {
            script.builder.append(", ");
          }
          Object item = tuple.get(index);
          typeParams[index].serializer.genScript(script, item);
        }

        script.level--;
        script.builder.append(")");
      }

      @Override
      protected void toStratoJson(GenScript script, Tuple tuple) {
        throw new IllegalArgumentException("Tuples are not supported in strato JSON");
      }
    };
  }

  public static Serializer<StructTuple> structTupleOf(
      ImmutableList<String> fieldNames, ImmutableList<Type> fieldTypes) {
    Preconditions.checkArgument(fieldNames.size() == fieldTypes.size());
    return new Serializer<StructTuple>() {

      @Override
      public void computeFingerprint(Hasher hasher, StructTuple structTuple) throws Exception {

        for (int index = 0; index < structTuple.size(); index++) {
          hasher.putInt(index);
          hasher.putUnencodedChars(fieldNames.get(index));
          fieldTypes.get(index).computerFingerprint(hasher);
          if (structTuple.get(index) != null) {
            fieldTypes.get(index).serializer.computeFingerprint(hasher, structTuple.get(index));

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Replace Tuple with StructTuple or a named thrift struct and serialize via thriftStructOf/structTupleOf if strato JSON support exists for that path.
  2. Keep tuples only on the fingerprint/genScript path and exclude them from strato JSON export.
  3. If strato JSON must carry the data, encode the tuple as a JSON array via a custom serializer branch (extend toStratoJson) instead of throwing.

Example fix

// before
Serializer<Tuple> t = Serializer.tupleOf(intOf(), stringOf());
t.genStratoJson(script, tuple); // throws Tuples are not supported in strato JSON

// after
StructTuple st = StructTuple(ImmutableList.of("i", "s"), ImmutableList.of(1, "x"));
Serializer.structTupleOf(names, types).genStratoJson(script, st);
Defensive patterns

Strategy: validation

Validate before calling

if (usesTuple(type)) {
  throw new IllegalArgumentException(featureName + " uses Tuple, not strato-JSON serializable");
}

Try / catch

catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Tuples are not supported")) {
    return fingerprintViaGenScript(tuple); // fallback path
  }
  throw e;
}

Prevention

When it happens

Trigger: Creating a serializer via Serializer.tupleOf(typeParams...) and invoking genStratoJson on a Tuple value; typically when a rule/feature typed as a tuple is exported or served through the strato JSON path.

Common situations: Using tuple-typed constants or columns in botmaker features that are then registered for strato discovery; refactoring a struct into a tuple and forgetting the JSON path; enabling strato serving on an existing tuple-typed feature.

Related errors


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