{"record":{"id":"f93137d6164ec8c0","repo":"xai-org/x-algorithm","slug":"field-name-s-is-not-an-underscore-followed-by-a-n","errorCode":null,"errorMessage":"field name %s is not an underscore followed by a number for tuple class %s","messagePattern":"field name (.+?) is not an underscore followed by a number for tuple class (.+?)","errorType":"exception","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/compiler/types/TupleType.java","lineNumber":56,"sourceCode":"                typeParams,\n                NON_GENERIC_TYPE_ID,\n                serializer)\n        ));\n  }\n\n  @Override\n  public Set<String> getFieldNames() {\n    Set<String> fieldNames = Sets.newHashSetWithExpectedSize(typeParams.size());\n    for (int i = 0; i < typeParams.size(); ++i) {\n      fieldNames.add(\"_\" + (i + 1));\n    }\n    return ImmutableSet.copyOf(fieldNames);\n  }\n\n  @Override\n  public Type getFieldType(String fieldName) throws SemanticCheckFailure {\n    if (!fieldName.startsWith(\"_\")) {\n      throw new SemanticCheckFailure(\n          String.format(\n              \"field name %s is not an underscore followed by a number for tuple class %s\",\n              fieldName,\n              toString()));\n    }\n\n    try {\n      return typeParams.get(Integer.valueOf(fieldName.substring(1)) - 1);\n    } catch (Throwable t) {\n      throw new SemanticCheckFailure(t);\n    }\n  }\n\n  @Override\n  public boolean isSetValue(Tuple obj, String fieldName) {\n    try {\n      return (fieldName.startsWith(\"_\"))\n          && Integer.valueOf(fieldName.substring(1)) - 1 < typeParams.size();","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/compiler/types/TupleType.java#L38-L74","documentation":"TupleType.getFieldType only accepts tuple positional names of the form '_' followed by a number ('_1', '_2', ...). Any other name throws SemanticCheckFailure.","triggerScenarios":"Calling getFieldType on a plain Tuple (not StructTuple) type with a named field like 'user_id' or '_abc' that is not underscore-plus-digits.","commonSituations":"Rules written with named field access on anonymous positional tuple types; assuming StructTuple semantics on a Tuple; schema change from StructTuple to Tuple.","solutions":["Use positional names '_1', '_2', ... matching tuple arity","Switch the type to a StructTuple if named access is required","Verify the tuple's arity via getTypeParams/getFieldNames before access"],"exampleFix":"// before\ntupleType.getFieldType(\"user_id\");\n// after\ntupleType.getFieldType(\"_1\");","handlingStrategy":"type-guard","validationCode":"if (!fieldName.matches(\"_\\\\d+\")) throw new IllegalArgumentException(\"use _N names\");","typeGuard":"boolean isPositionalName(String s) { return s.matches(\"_\\\\d+\"); }","tryCatchPattern":"catch SemanticCheckFailure; rewrite named access to positional or switch to StructTuple type","preventionTips":["Prefer StructTuple when named access is needed","Lint tuple field access patterns in rules"],"tags":["tuple","field-lookup","validation"],"backgroundTag":"unknown-field-name","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}