xai-org/x-algorithm · error · SemanticCheckFailure

field %s expects %s type but %s received.

Error message

field %s expects %s type but %s received.

What it means

ThriftOperator.checkThriftFieldTypes throws SemanticCheckFailure when the value expression's return type diverges from the thrift-declared type of the named field (checked via isDivergentTo). This enforces type safety when constructing or mutating thrift structs from expressions.

Source

Thrown at botmaker/src/java/com/twitter/botmaker/function/thrift/ThriftOperator.java:86

      ToPair pair = (ToPair) node;
      ASTNode first = pair.getChildren().get(0);
      ASTNode second = pair.getChildren().get(1);

      if (!(first instanceof Constant)) {
        continue;
      }

      Object value = ((Constant) first).getValue();
      if (!(value instanceof String)) {
        throw new SemanticCheckFailure(
            String.format("field name %s has to be a String.", value)
        );
      }

      String fieldName = (String) value;
      Type fieldType = type.getFieldType(fieldName);
      if (isDivergentTo(fieldType, second)) {
        throw new SemanticCheckFailure(
            String.format("field %s expects %s type but %s received.",
                fieldName, fieldType, second.getReturnType()));
      }
    }
  }

  private static boolean isDivergentTo(
      Type fieldType, ASTNode<?> node) throws SemanticCheckFailure {

    if (fieldType.typeBase == Set.class && node instanceof SetOperator) {
      Type elementType = fieldType.getTypeParams().get(0);
      for (ASTNode child : node.getChildren()) {
        if (isDivergentTo(elementType, child)) {
          return true;
        }
      }
      return false;
    }

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Align the value expression's type with the field's declared thrift type (cast/convert before the operator)
  2. Refresh type definitions after thrift schema changes and re-check the field type
  3. If the mismatch is expected, insert an explicit conversion function node

Example fix

// before
children = [Constant("count"), stringNode] // count is i64
// after
children = [Constant("count"), longNode] // matches i64 field
Defensive patterns

Strategy: type-guard

Validate before calling

Type fieldType = type.getFieldType(fieldName);
if (ThriftOperator.isDivergentTo(fieldType, valueNode)) {
  throw new IllegalArgumentException(fieldName + " expects " + fieldType + " but got " + valueNode.getReturnType());
}

Type guard

public static boolean fieldTypeMatches(FieldAccessibleType t, String field, ASTNode value) {
  return !ThriftOperator.isDivergentTo(t.getFieldType(field), value);
}

Try / catch

try {
  ThriftOperator.of(...);
} catch (SemanticCheckFailure e) {
  // include fieldName, expected vs actual type in the error report
}

Prevention

When it happens

Trigger: Passing a Long-typed expression for an i32/string field, a String for a bool field, or any pair where the value node's getReturnType() does not conform to type.getFieldType(fieldName).

Common situations: Schema evolution changing a field's type (i64 -> string), passing untyped/null literals, mismatched numeric widths between expression engine types and thrift types.

Related errors


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