{"record":{"id":"bd04d135b2e33ffc","repo":"xai-org/x-algorithm","slug":"sort-expects-a-collection-of-s-objects-but-gets","errorCode":null,"errorMessage":"Sort expects a collection of %s objects, but gets %s","messagePattern":"Sort expects a collection of (.+?) objects, but gets (.+?)","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/compiler/Compiler.java","lineNumber":1037,"sourceCode":"                \"Sort is expected to return %s but passed function returns %s\",\n                Type.LONG,\n                funcNode.getReturnType()));\n      }\n\n      context.removeScope();\n\n      ASTNode result = Sort.toSort(\n          exprText, varA, varB, funcNode, context.currentScopeId(), collectionNode);\n      return result;\n    } else if (root.getChildCount() == 2) {\n      ASTNode collectionNode = createASTNodeTree(context, root.getChild(1));\n      Type elementType = Type.OBJECT;\n      if (Collection.class.isAssignableFrom(collectionNode.getReturnType().typeBase)) {\n        elementType = collectionNode.getReturnType().getTypeParams().get(0);\n      }\n\n      if (!Comparable.class.isAssignableFrom(elementType.typeBase)) {\n        throw new SemanticCheckFailure(\n            String.format(\"Sort expects a collection of %s objects, but gets %s\",\n                Comparable.class.getName(),\n                elementType)\n        );\n      }\n\n      ASTNode result = Sort.toSort(exprText, collectionNode);\n      return result;\n    } else {\n      throw new SemanticCheckFailure(String.format(\n          \"%s node with invalid number of children: %d\", root.getText(), root.getChildCount()));\n    }\n  }\n\n  private ASTNode toBlock(CompilerContext context, Tree root)\n      throws ParseFailure, SemanticCheckFailure {\n    if (root.getChildCount() == 0) {\n      throw new SemanticCheckFailure(\"block body cannot be empty\");","sourceCodeStart":1019,"sourceCodeEnd":1055,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/compiler/Compiler.java#L1019-L1055","documentation":"Sort can only order collections whose element type implements java.lang.Comparable. The compiler inspects the collection's element type (defaulting to OBJECT when unknown) and rejects non-Comparable element types such as Thrift structs or maps.","triggerScenarios":"Sorting a collection of ThriftStruct objects, maps, or an untyped collection (element inferred as OBJECT) that is not Comparable.","commonSituations":"Trying to Sort structs directly instead of sorting with a comparator key, or sorting a heterogeneous/untyped collection where the element type cannot be proven Comparable.","solutions":["Use the two-argument Sort(coll, comparatorFn) form returning a Long key instead of the bare Sort","Convert elements to Comparable values (e.g. extract a Long/String field) before sorting","Ensure the collection is typed so its element type is known and Comparable"],"exampleFix":"// before\nresult = Sort(structList)\n// after\nresult = Sort(structList, (a, b) -> a.score - b.score)","handlingStrategy":"type-guard","validationCode":"Type elem = collectionType.getTypeParams().get(0);\nif (!Comparable.class.isAssignableFrom(elem.typeBase)) useComparatorSort();","typeGuard":"static boolean isSortable(Type elementType) { return Comparable.class.isAssignableFrom(elementType.typeBase); }","tryCatchPattern":"catch (SemanticCheckFailure e) { if (e.getMessage().contains(\"Sort expects a collection\")) switchToComparatorForm(); else throw e; }","preventionTips":["Default to the two-argument Sort with a Long comparator key","Type collections precisely so element types are known"],"tags":["botmaker","sort","comparable","type-check"],"backgroundTag":"element-not-comparable","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}