{"record":{"id":"4b08a774a0087c80","repo":"apache/hadoop","slug":"unexpected-end-of-block","errorCode":null,"errorMessage":"Unexpected end of block","messagePattern":"Unexpected end of block","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/util/CountersStrings.java","lineNumber":193,"sourceCode":"  // sequences. Throws ParseException if an incomplete block is found else\n  // returns null.\n  private static String getBlock(String str, char open, char close,\n                                IntWritable index) throws ParseException {\n    StringBuilder split = new StringBuilder();\n    int next = StringUtils.findNext(str, open, StringUtils.ESCAPE_CHAR,\n                                    index.get(), split);\n    split.setLength(0); // clear the buffer\n    if (next >= 0) {\n      ++next; // move over '('\n\n      next = StringUtils.findNext(str, close, StringUtils.ESCAPE_CHAR,\n                                  next, split);\n      if (next >= 0) {\n        ++next; // move over ')'\n        index.set(next);\n        return split.toString(); // found a block\n      } else {\n        throw new ParseException(\"Unexpected end of block\", next);\n      }\n    }\n    return null; // found nothing\n  }\n\n  /**\n   * Parse a pre 0.21 counters string into a counter object.\n   * @param <C> type of the counter\n   * @param <G> type of the counter group\n   * @param <T> type of the counters object\n   * @param compactString to parse\n   * @param counters an empty counters object to hold the result\n   * @return the counters object holding the result\n   * @throws ParseException\n   */\n  @SuppressWarnings(\"deprecation\")\n  public static <C extends Counter, G extends CounterGroupBase<C>,\n                 T extends AbstractCounters<C, G>>","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/util/CountersStrings.java#L175-L211","documentation":"CountersStrings.getBlock() parses pre-0.21 compact counter strings shaped 'GROUP*(counter=value)(counter=value)...': after consuming an opening '(' it scans for the matching ')' honoring backslash escapes. If the string ends before the closing paren is found, parsing aborts with ParseException 'Unexpected end of block'.","triggerScenarios":"Parsing a legacy counters string where a block opens but never closes: a group or counter display name containing an unescaped '(', or a truncated/malformed string passed to the parser.","commonSituations":"Reading old job history or preserved counters strings; hand-built counter strings (e.g., setDisplay names with parentheses) fed back into the parser; string truncation at a fixed-size boundary before parsing.","solutions":["Escape parentheses in counter/group display names with a backslash (StringUtils.ESCAPE_CHAR) when producing strings.","Produce strings via Counters.toEscapedCompactString() rather than manual formatting so escaping is handled.","Validate that every '(' has a matching unescaped ')' before parsing legacy strings.","If the string is truncated, obtain the full value (increase the storage/column width) before parsing."],"exampleFix":"// before: unescaped paren opens a block that never closes\nString s = \"Gr(oup*(m1=1)\";\n// after: escape it so the group block parses\nString s = \"Gr\\\\(oup*(m1=1)\";","handlingStrategy":"try-catch","validationCode":"// Cheap balance check honoring backslash escapes, before parsing a legacy counters string\nstatic boolean blocksBalanced(String s) {\n  int depth = 0;\n  for (int i = 0; i < s.length(); i++) {\n    char ch = s.charAt(i);\n    if (ch == '\\\\') { i++; } else if (ch == '(') { depth++; } else if (ch == ')') { depth--; }\n    if (depth < 0) { return false; }\n  }\n  return depth == 0;\n}","typeGuard":null,"tryCatchPattern":"catch (org.apache.hadoop.util.StringUtils.ParseException e) { if (\"Unexpected end of block\".equals(e.getMessage())) { /* input truncated or parens unescaped: log the raw string, skip or repair it */ } else { throw e; } }","preventionTips":["Produce counters strings only via Counters.toEscapedCompactString().","Escape parentheses in counter and group display names when constructing strings by hand.","Do not truncate counters strings in storage before parsing them back."],"tags":["hadoop","mapreduce","counters","parsing","legacy"],"backgroundTag":"unbalanced-parentheses","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}