fix: updating error messages thrown to end users#14115
Conversation
|
hey @yihua : can you take up the review on this. |
| .orElseThrow(() -> new HoodieException( | ||
| "Table version mismatch detected. " | ||
| + "The table was created with a Hudi version that has table version code " + versionCode | ||
| + " but you're using an older version.\n" | ||
| + "Likely you are using a lower hudi binary version to read a table written using higher hudi version which is not supported. " | ||
| + "To fix this issue:\n" | ||
| + " - Please upgrade your readers to use the same version as writers\n" | ||
| + " - Table version code: " + versionCode + "\n" | ||
| + " - Current supported versions: " + Arrays.toString(HoodieTableVersion.values()) + "\n" | ||
| + "See: https://hudi.apache.org/docs/migration_guide for more information")); |
There was a problem hiding this comment.
The error message does not match the actual error. The exception is thrown if the table version is not in the range of 0 to 9 (inclusive). There is no version comparison in this method.
There was a problem hiding this comment.
you are right, fixed it
There was a problem hiding this comment.
I am pushing out a commit to fix this.
this can only happen if X hudi lib version is used to read a table written by higher (Y) hudi version, where X and Y refers to table version.
| "'_hoodie_is_deleted' field is missing for some of the incoming records.\n\n" | ||
| + "The table schema requires '_hoodie_is_deleted' to be non-null, but some records lack this field.\n\n" | ||
| + "To fix:\n" | ||
| + " Ensure ALL records have '_hoodie_is_deleted' field set (true/false)\n\n" | ||
| + "Original error: " + errorMessage, e); |
There was a problem hiding this comment.
Avoid newline character in the error message?
| writtenRecordCount.incrementAndGet(); | ||
| } catch (RuntimeException e) { | ||
| String errorMessage = e.getMessage() != null ? e.getMessage() : ""; | ||
| if (isRequiredFieldNullError(errorMessage) && errorMessage.contains("_hoodie_is_deleted")) { |
There was a problem hiding this comment.
Where does these exceptions come from? Could errorMessage.contains be avoided and the source to throw an exception of specific classes which can be caught here?
There was a problem hiding this comment.
It is thrown by Apache Parquet library. It does not provide custom exception types like ParquetValidationException or RequiredFieldNullException. It only throws genericRuntimeException and we kind of need string parsing to log proper error message in this case
There was a problem hiding this comment.
guess we can avoid this fix. exiting error msg
Null-value for required field: _hoodie_is_deleted
would suffice. I just don't feel intercepting at this layer just to add more enhancement to error msg is not worth it
| List<String> errorKeys = HoodieJavaRDD.getJavaRDD(writeStatusesOpt.get()) | ||
| .filter(WriteStatus::hasErrors) | ||
| .flatMap(ws -> ws.getErrors().keySet().stream().iterator()) | ||
| .take(10) | ||
| .stream() | ||
| .map(Object::toString) | ||
| .collect(Collectors.toList()); | ||
|
|
||
| String errorSummary = String.format( | ||
| "%s operation failed with %d error(s).\n\nFailed records (first %d of %d):\n%s\n\n" | ||
| + "Check for error stacktraces in the driver logs which could give more information on the failure.", | ||
| writeOperationType, | ||
| totalErroredRecords, | ||
| Math.min(10, errorKeys.size()), | ||
| errorKeys.size(), | ||
| errorKeys.stream() | ||
| .map(k -> " - Record Key: " + k) | ||
| .collect(Collectors.joining("\n"))); | ||
|
|
||
| LOG.error(errorSummary); |
There was a problem hiding this comment.
We cannot log record keys which can contain PII, potentially violating data compliance.
There was a problem hiding this comment.
right, updated it with just count
| + " - For Hive 2.x: Use hudi-spark-bundle with 'hive2' classifier\n" | ||
| + " - For Hive 3.x: Use hudi-spark-bundle with 'hive3' classifier\n" |
There was a problem hiding this comment.
It happens when user has Spark with Hive 3.x, but uses hudi-spark-bundle (which has Hive 2.x shaded inside)
It can happen because Spark loads Hive 3.x classes from its own JARs -> Hudi bundle expects Hive 2.x classes (but shaded/renamed) -> Class loader tries to match them but fails because packages don't match -> Throws confusing error about "class X not org.apache.hudi.org.apache.hadoop...". The above exception with error message describes the issue properly.
| return "Cannot read Hudi table schema - required data file is missing.\n\n" | ||
| + "This can happen due to:\n" | ||
| + " 1. Aggressive cleaner retention compared to query run times\n" | ||
| + " 2. Manual file deletions (timeline files or data files)\n" | ||
| + " 3. Concurrent writers without proper locking or configurations set\n\n" | ||
| + "Depending on the root cause, mitigation might differ.\n\n" | ||
| + "Original error: " + errorMessage; |
There was a problem hiding this comment.
The error message does not make sense. The main cause is that the commit metadata does not have the table schema and there is no data file to check the schema either.
There was a problem hiding this comment.
right, haven't put that properly previously, updated it
| + "This table version is not recognized by this Hudi version.%n%n" | ||
| + "This can happen if:%n" | ||
| + " (1) The table was created with a newer version of Hudi (upgrade your readers),%n" | ||
| + " (2) The table was created with an older version of Hudi (downgrade your readers or upgrade the table),%n" |
There was a problem hiding this comment.
2nd is not right.
higher versions of hudi can read older versions
| String errorMessage = e.getMessage() != null ? e.getMessage() : e.getClass().getName(); | ||
| if (e instanceof java.io.FileNotFoundException) { | ||
| return String.format( | ||
| "Cannot read Hudi table schema.%n%n" |
There was a problem hiding this comment.
If we hit FileNotFoundException, then it means, the data file was deleted by some means right.
- Aggressive cleaner retention compared to query run times
- Manual file deletions (timeline files or data files)
- Concurrent writers without proper locking or configurations set
There was a problem hiding this comment.
hey @yihua : this is specifically when FileNotFoundException. not sure if the error msg lines up with that.
| writtenRecordCount.incrementAndGet(); | ||
| } catch (RuntimeException e) { | ||
| String errorMessage = e.getMessage() != null ? e.getMessage() : ""; | ||
| if (isRequiredFieldNullError(errorMessage) && errorMessage.contains("_hoodie_is_deleted")) { |
There was a problem hiding this comment.
guess we can avoid this fix. exiting error msg
Null-value for required field: _hoodie_is_deleted
would suffice. I just don't feel intercepting at this layer just to add more enhancement to error msg is not worth it
nsivabalan
left a comment
There was a problem hiding this comment.
@yihua : I have pushed a commit to address my own feedback.
feel free to review and land the patch if its good.
|
hey @yihua : feel free to send out a follow up PR for any additional feedback you have. |
--------- Co-authored-by: sivabalan <n.siva.b@gmail.com>
Describe the issue this Pull Request addresses
This PR just updates the error messages that needs improvement in letting the users know the issue causing the error.
Summary and Changelog
This PR just updates the error messages that needs improvement in letting the users know the issue causing the error.
Impact
Better user interaction
Risk Level
none
Documentation Update
none, its just for better usability
Contributor's checklist