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

ThriftStructOperator.checkThriftFieldTypes throws SemanticCheckFailure when a (fieldName, value) pair's first element is a Constant that is not a String — identical semantics to ThriftOperator but for struct-construction operators. Field names must be string literals.

Source

Thrown at botmaker/src/java/com/twitter/botmaker/function/thrift/ThriftStructOperator.java:77

  public static void checkThriftFieldTypes(
      ThriftStructType 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. Make the first element of every pair a String constant with the exact thrift field name
  2. Verify argument pair ordering in your expression builder
  3. Add build-time assertions that names are String constants

Example fix

// before
children = [Constant(true), valueNode]
// after
children = [Constant("enabled"), 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("struct 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 {
  ThriftStructOperator.of(...);
} catch (SemanticCheckFailure e) {
  // report offending constant value and pair index
}

Prevention

When it happens

Trigger: Building a thrift struct expression with a non-string constant field name, e.g. ThriftStructOperator children (Constant(3.14), value) or (Constant(true), value).

Common situations: Expression generators using field IDs or enums instead of names, swapped argument pairs, copy-paste from value nodes into the name slot.

Related errors


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