{"record":{"id":"82dc12915cb89642","repo":"xai-org/x-algorithm","slug":"contains-expects-input-of-string-map-set-or-coll","errorCode":null,"errorMessage":"Contains expects input of String, Map, Set or Collection types but %s received","messagePattern":"Contains expects input of String, Map, Set or Collection types but (.+?) received","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/function/collection/Contains.java","lineNumber":55,"sourceCode":"  private static final Signature SIGNATURE = new Signature(\n      ImmutableList.of(\n          Type.OBJECT,\n          Type.OBJECT),\n      Type.BOOLEAN\n  );\n\n  public Contains(String exprText, ImmutableList<ASTNode> children) throws SemanticCheckFailure {\n    super(exprText, validateASTNodesAndModifyType(children));\n  }\n\n  private static ImmutableList<ASTNode> validateASTNodesAndModifyType(\n      ImmutableList<ASTNode> children) throws SemanticCheckFailure {\n    Class<?> typeBase = children.get(0).getReturnType().typeBase;\n    if (!Object.class.equals(typeBase)\n        && !String.class.equals(typeBase)\n        && !Collection.class.isAssignableFrom(typeBase)\n        && !Map.class.isAssignableFrom(typeBase)) {\n      throw new SemanticCheckFailure(String.format(\n          \"Contains expects input of String, Map, Set or Collection types but %s received\",\n          typeBase.getName()));\n    }\n\n    if (Collection.class.isAssignableFrom(typeBase) && !Set.class.isAssignableFrom(typeBase)) {\n      ASTNode setifiedCollection = new ToSet(\"ToSet\", ImmutableList.of(children.get(0)));\n      return ImmutableList.of(setifiedCollection, children.get(1));\n    }\n    return children;\n  }\n\n  @Override\n  public Signature getSignature() {\n    return SIGNATURE;\n  }\n\n  @Override\n  protected CacheLevel getCacheLevel() {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/function/collection/Contains.java#L37-L73","documentation":"Contains() only accepts a first argument whose static return type is String, Set, Collection, Map, or a generic Object. Any other typeBase (e.g. Long, Boolean, StructTuple) fails semantic checking with this message. Note that a non-Set Collection is automatically coerced via ToSet before containment is checked.","triggerScenarios":"Passing Contains(someLong, x), Contains(true, x), or Contains(structTuple, x). Also passing a typed value whose inferred typeBase is not in the allowed set.","commonSituations":"Chaining Contains after a function that returns a scalar (Count, Size), or after refactoring a pipeline so the first argument's type changed from a collection to a scalar.","solutions":["Change the first argument to a String, Set, Collection or Map expression","If the value might be anything, cast/annotate it as Object so the generic path applies","Wrap the value in a coercion function that produces a collection (e.g. Split for strings)"],"exampleFix":"// before\nContains(Count(items), 3)\n// after\nContains(items, 3) // or use the collection directly","handlingStrategy":"type-guard","validationCode":"// rule-language: coerce unknown input before Contains\nContains(ToString(maybeAny), \"needle\")","typeGuard":"// host code: check the child's static type before building Contains\nClass<?> base = child.getReturnType().typeBase;\nboolean ok = Object.class.equals(base) || String.class.equals(base)\n    || Collection.class.isAssignableFrom(base) || Map.class.isAssignableFrom(base);","tryCatchPattern":null,"preventionTips":["Keep Contains' first argument a String/Set/Collection/Map expression","Remember non-Set Collections are auto-coerced via ToSet","Re-check argument types after refactoring pipelines"],"tags":["botmaker","semantic-check","type-mismatch","contains"],"backgroundTag":"function-argument-type-mismatch","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}