xai-org/x-algorithm · error · SemanticCheckFailure

field name %s has to be a String.

Error message

field name %s has to be a String.

What it means

ThriftOperator.checkThriftFieldTypes throws SemanticCheckFailure when the first child of a (fieldName, value) argument pair is a Constant whose value is not a String. Thrift field-setting operators name fields with string literals; non-string constants (numbers, booleans) are rejected.

Source

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

  public static void checkThriftFieldTypes(
      ThriftType type, List<ASTNode> nodes) throws SemanticCheckFailure {
    for (ASTNode node : nodes) {
      if (!(node instanceof ToPair)) {
        continue;
      }

      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) {

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Ensure the first argument of each pair is a String constant naming the thrift field
  2. Check argument ordering: field name literal first, value expression second
  3. If generating expressions programmatically, assert the constant is a String at build time

Example fix

// before
children = [Constant(1), valueNode]
// after
children = [Constant("userId"), valueNode]
Defensive patterns

Strategy: validation

Validate before calling

for (int i = 0; i + 1 < children.size(); i += 2) {
  ASTNode first = children.get(i);
  if (first instanceof Constant && !(((Constant) first).getValue() instanceof String)) {
    throw new IllegalArgumentException("field name must be a String constant");
  }
}

Type guard

public static boolean isStringConstant(ASTNode n) {
  return n instanceof Constant && ((Constant) n).getValue() instanceof String;
}

Try / catch

try {
  ThriftOperator.of(...);
} catch (SemanticCheckFailure e) {
  // surface argument pair index and constant value for debugging
}

Prevention

When it happens

Trigger: Constructing a thrift operator call with a non-string constant as the field name, e.g. ThriftOperator with children (Constant(1), valueNode) instead of (Constant("fieldName"), valueNode).

Common situations: Code-generated expressions that emit numeric field IDs instead of names, typos where the value node comes first, expression-builder bugs swapping argument order.

Related errors


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