{"record":{"id":"dab1e28f0b059bcb","repo":"xai-org/x-algorithm","slug":"type-s-does-not-support-index-accessor","errorCode":null,"errorMessage":"Type %s does not support index accessor","messagePattern":"Type (.+?) does not support index accessor","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/function/collection/IndexAccessor.java","lineNumber":47,"sourceCode":"  public static ASTNode mkIndexAccessor(\n      String exprText, ASTNode exprNode, ASTNode indexNode) throws SemanticCheckFailure {\n\n    Type returnType = exprNode.getReturnType();\n    Type indextype = indexNode.getReturnType();\n    if (returnType.getBase().equals(List.class)\n        && returnType.getTypeParams().size() == 1\n        && indextype.equals(Type.pairOf(Type.LONG, Type.LONG))) {\n      return listPairAccessor(exprText, exprNode, indexNode);\n    } else if (returnType.getBase().equals(List.class)\n        && returnType.getTypeParams().size() == 1) {\n      return listIndexAccessor(exprText, exprNode, indexNode);\n    } else if (returnType.getBase().equals(Map.class)\n        && returnType.getTypeParams().size() == 2) {\n      return mapKeyAccessor(exprText, exprNode, indexNode);\n    } else if (returnType.getBase().equals(Object.class)) {\n      return objectIndexAccessor(exprText, exprNode, indexNode);\n    } else {\n      throw new SemanticCheckFailure(\n          String.format(\"Type %s does not support index accessor\", returnType));\n    }\n  }\n\n  private static ASTNode listPairAccessor(\n      String exprText, ASTNode exprNode, ASTNode indexNode) throws SemanticCheckFailure {\n\n    Type returnType = exprNode.getReturnType();\n    Type indextype = indexNode.getReturnType();\n\n    Signature signature = new Signature(\n        ImmutableList.of(returnType, indextype),\n        returnType);\n    return new IndexAccessor(exprText, ImmutableList.of(exprNode, indexNode)) {\n      @Override\n      public Signature getSignature() {\n        return signature;\n      }","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/function/collection/IndexAccessor.java#L29-L65","documentation":"The index accessor (expr[index]) supports Lists, Lists of Pairs, two-param Maps, and untyped Object expressions. Applying an index to any other static return type (e.g. Long, Boolean, StructTuple with different arity) fails semantic checking with this message.","triggerScenarios":"Writing myLong[0], myStruct['field'], or map[key] where the map's type params are not exactly 2.","commonSituations":"Using struct field syntax on a non-map, indexing a scalar returned by a previous function, or a typed map whose type parameters were lost/added.","solutions":["Access struct fields with the appropriate field-access function instead of index syntax","Ensure maps are typed with exactly two type params (K, V)","Cast the expression to Object before indexing when the runtime type is genuinely indexable"],"exampleFix":"// before\nsomeScalar[0]\n// after\nGet(someList, 0)","handlingStrategy":"type-guard","validationCode":"// rule-language: use explicit accessors per type\nGet(list, 0) / GetByKey(map, key)","typeGuard":"// host code before mkIndexAccessor\nType rt = exprNode.getReturnType();\nboolean supports = rt.getBase().equals(List.class)\n    || (rt.getBase().equals(Map.class) && rt.getTypeParams().size() == 2)\n    || rt.getBase().equals(Object.class);","tryCatchPattern":null,"preventionTips":["Only index Lists, 2-param Maps, and Object-typed expressions","Use field accessors for structs"],"tags":["botmaker","semantic-check","type-mismatch","index-accessor"],"backgroundTag":"invalid-index-access","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}