xai-org/x-algorithm · error · SemanticCheckFailure

%s cannnot be converted to %s. missing field %s.

Error message

%s cannnot be converted to %s. missing field %s.

What it means

StructTupleType.converter builds an index map to convert one StructTuple layout into another. If the target StructTupleType declares a field name that does not exist in this type, conversion cannot proceed and SemanticCheckFailure is thrown.

Source

Thrown at botmaker/src/java/com/twitter/botmaker/compiler/types/StructTupleType.java:91

  @Override
  public Type replaceTypeArguments(Map<Long, Type> mappedTypes) throws SemanticCheckFailure {
    ImmutableList<Type> params = this.getTypeParams();
    List<Type> inferredTypeParams = Lists.newArrayListWithCapacity(params.size());
    for (Type typeParam : params) {
      Type replacement = typeParam.replaceTypeArguments(mappedTypes);
      inferredTypeParams.add(replacement);
    }

    return ofStructTuple(fieldNames, ImmutableList.copyOf(inferredTypeParams));
  }

  public Function<StructTuple, StructTuple> converter(
      StructTupleType structTupleType) throws SemanticCheckFailure {
    int[] indexMap = new int[structTupleType.fieldNames.size()];
    for (int i = 0; i < structTupleType.fieldNames.size(); i++) {
      int fi = fieldNames.indexOf(structTupleType.fieldNames.get(i));
      if (fi < 0) {
        throw new SemanticCheckFailure(
            String.format("%s cannnot be converted to %s. missing field %s.",
                this,
                structTupleType,
                structTupleType.fieldNames.get(i))
        );
      }
      if (!fieldTypes.get(fi).equals(structTupleType.fieldTypes.get(i))) {
        throw new SemanticCheckFailure(
            String.format("%s cannnot be converted to %s. field type %s mismatch.",
                this,
                structTupleType,
                structTupleType.fieldNames.get(i))
        );
      }
      indexMap[i] = fi;
    }

    return Function.func((StructTuple t) -> {

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Regenerate/redeploy both StructTuple classes from the same thrift schema version so field sets match
  2. Change the rule to convert to a StructTupleType whose field names are a subset of the source
  3. Pre-check field coverage before calling converter

Example fix

// before
Function<StructTuple, StructTuple> f = srcType.converter(dstType); // dst has extra field
// after
boolean covers = srcType.getFieldNames().containsAll(dstType.getFieldNames());
Function<StructTuple, StructTuple> f = covers ? srcType.converter(dstType) : null;
Defensive patterns

Strategy: validation

Validate before calling

Set<String> src = structTupleTypeA.getFieldNames();
if (!src.containsAll(structTupleTypeB.getFieldNames())) {
  throw new IllegalArgumentException("target has fields missing in source");
}

Try / catch

catch SemanticCheckFailure around converter(); report the missing field name from the message to the rule author

Prevention

When it happens

Trigger: Calling converter(targetStructTupleType) where targetStructTupleType.fieldNames contains a name absent from this.fieldNames — e.g. joining or casting two struct tuples whose schemas were generated from different thrift structs.

Common situations: Schema drift: producer pipeline was regenerated with a new field while the botmaker rule still uses the old (or new) StructTuple class; using incompatible tuple classes after a thrift schema change.

Related errors


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