xai-org/x-algorithm · error · SemanticCheckFailure

function passed to Foldl() returns %s but seed value is a %s

Error message

function passed to Foldl() returns %s but seed value is a %s

What it means

Foldl (left fold) requires the folding function's return type to be compatible with the seed value's type. If the function diverges from the seed type, the accumulator type would change across iterations, which the statically typed DSL forbids.

Source

Thrown at botmaker/src/java/com/twitter/botmaker/compiler/Compiler.java:931

    Type fromType = Type.OBJECT;
    if (Collection.class.isAssignableFrom(collectionNode.getReturnType().typeBase)) {
      fromType = collectionNode.getReturnType().getTypeParams().get(0);
    }
    Type seedType = seedValueNode.getReturnType();

    CompilerScope scope = context.addScope();
    long scopeId = context.currentScopeId();
    Parameter parameterA = Parameter.scope(
        varA, seedType, scopeId, seedValueNode);
    scope.defineVariable(parameterA);

    Parameter parameterB = Parameter.scope(
        varB, fromType, scopeId, collectionNode);
    scope.defineVariable(parameterB);

    ASTNode funcNode = createASTNodeTree(context, funcTree);
    if (Type.isDivergentTo(funcNode.getReturnType(), seedType)) {
      throw new SemanticCheckFailure(
          String.format(
              "function passed to Foldl() returns %s but seed value is a %s",
              funcNode.getReturnType(),
              seedType));
    }

    context.removeScope();

    ASTNode result = Fold.createFoldl(exprText, varA, varB, funcNode, seedValueNode,
        context.currentScopeId(), collectionNode);
    return result;
  }

  private ASTNode toFoldl1(CompilerContext context, String exprText, Tree root)
      throws ParseFailure, SemanticCheckFailure {
    String varA = getVariableName(root.getChild(1));
    String varB = getVariableName(root.getChild(2));
    ASTNode collectionNode = createASTNodeTree(context, root.getChild(4));

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Make the seed's type match the function's return type
  2. Rewrite the folding function so it returns the same type as its seed argument
  3. If changing types mid-fold is needed, do the conversion in an outer expression instead

Example fix

// before
Foldl(nums, 0L, (acc, x) -> ToDouble(acc + x))
// after
Foldl(nums, 0L, (acc, x) -> acc + x)
Defensive patterns

Strategy: type-guard

Type guard

// in DSL: ensure fold fn return type == seed type before compiling
if (!fnReturnType.equals(seedType)) throw new IllegalArgumentException("Foldl seed/fn type mismatch");

Try / catch

catch (SemanticCheckFailure e) { if (e.getMessage().contains("Foldl")) surfaceTypeHint(e); else throw e; }

Prevention

When it happens

Trigger: `Foldl(collection, seed, fn)` where fn returns e.g. Double while seed is a Long, or fn returns a struct while the seed is a primitive.

Common situations: Writing a fold that accumulates a different type than it takes (e.g. summing into a string, or building a list from an int seed), or assuming implicit numeric coercion that Botmaker does not perform.

Related errors


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