{"record":{"id":"0285ed33c602ddbf","repo":"apache/hadoop","slug":"error-deserializing-string","errorCode":null,"errorMessage":"Error deserializing string.","messagePattern":"Error deserializing string\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-streaming/src/main/java/org/apache/hadoop/record/Utils.java","lineNumber":156,"sourceCode":"      case '%':\n        sb.append(\"%25\");\n        break;\n      default:\n        sb.append(c);\n      }\n    }\n    return sb.toString();\n  }\n  \n  /**\n   *\n   * @param s\n   * @throws java.io.IOException\n   * @return\n   */\n  static String fromCSVString(String s) throws IOException {\n    if (s.charAt(0) != '\\'') {\n      throw new IOException(\"Error deserializing string.\");\n    }\n    int len = s.length();\n    StringBuilder sb = new StringBuilder(len-1);\n    for (int i = 1; i < len; i++) {\n      char c = s.charAt(i);\n      if (c == '%') {\n        char ch1 = s.charAt(i+1);\n        char ch2 = s.charAt(i+2);\n        i += 2;\n        if (ch1 == '0' && ch2 == '0') {\n          sb.append('\\0');\n        } else if (ch1 == '0' && ch2 == 'A') {\n          sb.append('\\n');\n        } else if (ch1 == '0' && ch2 == 'D') {\n          sb.append('\\r');\n        } else if (ch1 == '2' && ch2 == 'C') {\n          sb.append(',');\n        } else if (ch1 == '7' && ch2 == 'D') {","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-streaming/src/main/java/org/apache/hadoop/record/Utils.java#L138-L174","documentation":"Utils.fromCSVString() decodes the CSV-escaping produced by Utils.toCSVString(), which wraps strings in single quotes ('...'). If the input's first character is not a quote character, the input is not a CSV-encoded record string and the method throws IOException 'Error deserializing string.'.","triggerScenarios":"Calling fromCSVString (directly or via CsvRecordInput.readString) with a raw unquoted string, the wrong field/column from a CSV record, a truncated record, or data produced by a different serializer or Hadoop version with a different framing convention.","commonSituations":"Interoperability bugs where one side writes with toCSVString and the other side reads plain text, hand-crafted CSV test data missing the leading quote, or record streams corrupted by encoding/transfer so the framing character is lost.","solutions":["Only feed fromCSVString with values produced by Utils.toCSVString() on the same Hadoop version","Log the offending value hex-dumped when the exception fires to find where the framing was lost","Check that the record being parsed is aligned (not off-by-one field) and not truncated","Replace org.apache.hadoop.record usage with Avro/Writable, which have unambiguous framing"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// guard before decoding\nstatic boolean isCsvEncodedString(String s) {\n  return s != null && s.length() >= 2 && s.charAt(0) == '\\'' && s.charAt(s.length() - 1) == '\\'';\n}\nif (!isCsvEncodedString(field)) throw new IllegalArgumentException(\"Not a record-CSV string: \" + field);","typeGuard":null,"tryCatchPattern":"catch IOException around CsvRecordInput.readString()/Utils.fromCSVString and reject the whole record (log the raw field), since partial CSV state is unrecoverable.","preventionTips":["Only decode values produced by toCSVString() from the same Hadoop version","Round-trip test writer/reader pairs when changing versions","Treat framing errors as data-integrity failures: quarantine the record, don't skip silently"],"tags":["hadoop-record","csv","deserialization","deprecated","data-format"],"backgroundTag":"malformed-input-data","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}