xai-org/x-algorithm · error · SemanticCheckFailure

expects <name>: <value> pairs, but a %s received

Error message

expects <name>: <value> pairs, but a %s received

What it means

When Copy() targets a StructTuple, every override argument (index 1..n) must literally be a ToPair node (i.e. fieldName: value syntax). Any other AST node type fails semantic checking with this message. Note this check is stricter than the map path: it requires the node to be a ToPair instance, not merely pair-like.

Source

Thrown at botmaker/src/java/com/twitter/botmaker/function/collection/Copy.java:118

  private static Copy ofStructTuple(ImmutableList<ASTNode> children) throws SemanticCheckFailure {
    StructTupleType structTupleType = (StructTupleType) children.get(0).getReturnType();

    List<String> fieldNames = Lists.newArrayList(structTupleType.fieldNames);
    List<Type> fieldTypes = Lists.newArrayList(structTupleType.fieldTypes);

    ImmutableList.Builder<Type> argTypeBuilder = ImmutableList.builder();
    argTypeBuilder.add(structTupleType);

    ImmutableList.Builder<ASTNode> argBuilder = ImmutableList.builder();
    argBuilder.add(children.get(0));

    int[] overriddenFieldIndices = new int[children.size()];

    for (int i = 1; i < children.size(); i++) {
      ASTNode child = children.get(i);

      if (!(child instanceof ToPair)) {
        throw new SemanticCheckFailure(
            String.format("expects <name>: <value> pairs, but a %s received", child));
      }

      String fieldName = ((Constant) child.getChildren().get(0)).getValue().toString();
      Type fieldType = ((ASTNode) child.getChildren().get(1)).getReturnType();

      argBuilder.add((ASTNode) child.getChildren().get(1));
      argTypeBuilder.add(fieldType);

      int fieldIndex = fieldNames.indexOf(fieldName);
      if (fieldIndex < 0) {
        fieldNames.add(fieldName);
        fieldTypes.add(fieldType);
        overriddenFieldIndices[i] = fieldNames.size() - 1;
      } else if (!Type.isDivergentTo(fieldTypes.get(fieldIndex), fieldType)) {
        overriddenFieldIndices[i] = fieldIndex;
      } else {
        throw new SemanticCheckFailure(

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Use explicit field override syntax: Copy(myStruct, fieldName: value)
  2. When building the AST, wrap name/value children in ToPair nodes before calling Copy.of

Example fix

// before
Copy(userStruct, "bob")
// after
Copy(userStruct, name: "bob")
Defensive patterns

Strategy: validation

Validate before calling

// host code: require ToPair nodes for struct Copy
for (int i = 1; i < children.size(); i++) {
  if (!(children.get(i) instanceof ToPair)) {
    throw new IllegalArgumentException("expected fieldName: value, got " + children.get(i));
  }
}

Prevention

When it happens

Trigger: Calling Copy(struct, bareValue), Copy(struct, anotherStruct), or passing a computed expression node where a literal name: value pair is required.

Common situations: Programmatically constructing the children list and including non-ToPair nodes; refactoring struct update syntax to positional values.

Related errors


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