[ 
https://issues.apache.org/jira/browse/HBASE-29678?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Daniel Roudnitsky updated HBASE-29678:
--------------------------------------
    Description: 
If a scan with a filter using BigDecimalComparator encounters a row/column/byte 
array which was not encoded properly using Bytes.toBytes(BigDecimal) and is too 
short to be a BigDecimal, the scan RPC will fail with a NullPointerException, 
and the client will retry excessively until exhausting all retries, and the 
operation will fail with RetriesExhausted and a trace that looks like:
{code:java}
RetriesExhausted Failed after attempts=13, exceptions:
2025-10-20T19:31:23.525Z, java.io.IOException: java.io.IOException: Cannot read 
field "scale" because "val" is null
        at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:525)
        at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:124)
        at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:102)
        at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:82)
Caused by: java.lang.NullPointerException: Cannot read field "scale" because 
"val" is null
        at java.base/java.math.BigDecimal.compareTo(BigDecimal.java:3124)
        at 
org.apache.hadoop.hbase.filter.BigDecimalComparator.compareTo(BigDecimalComparator.java:72)
        at 
org.apache.hadoop.hbase.PrivateCellUtil.compareValue(PrivateCellUtil.java:1341)
        at 
org.apache.hadoop.hbase.filter.ColumnValueFilter.compareValue(ColumnValueFilter.java:128)
        at 
org.apache.hadoop.hbase.filter.ColumnValueFilter.filterCell(ColumnValueFilter.java:111)
        at 
org.apache.hadoop.hbase.regionserver.querymatcher.UserScanQueryMatcher.matchColumn(UserScanQueryMatcher.java:166)
        at 
org.apache.hadoop.hbase.regionserver.querymatcher.NormalUserScanQueryMatcher.match(NormalUserScanQueryMatcher.java:80)
        at 
org.apache.hadoop.hbase.regionserver.StoreScanner.next(StoreScanner.java:653)
        at 
org.apache.hadoop.hbase.regionserver.KeyValueHeap.next(KeyValueHeap.java:153)
        at 
org.apache.hadoop.hbase.regionserver.RegionScannerImpl.populateResult(RegionScannerImpl.java:348)
        at 
org.apache.hadoop.hbase.regionserver.RegionScannerImpl.nextInternal(RegionScannerImpl.java:520)
        at 
org.apache.hadoop.hbase.regionserver.RegionScannerImpl.nextRaw(RegionScannerImpl.java:285)
        at 
org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(RSRpcServices.java:3430)
        at 
org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(RSRpcServices.java:3703)
        at 
org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:45423)
        at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:458)
        ... 3 more
2025-10-20T19:31:23.645Z, java.io.IOException: java.io.IOException: Cannot read 
field "scale" because "val" is null
... {code}
+Root cause+ 
BigDecimalComparator#compareTo relies on ByteBufferUtils.toBigDecimal to 
convert the input byte array to BigDecimal, and ByteBufferUtils.toBigDecimal 
will return null if the byte array is too short. We don’t do a null check 
before doing the comparison , which leads to a NullPointerException that 
bubbles up the region server call stack which the client will treat as 
retryable exception

+Proposed solution+ 
Add a null check before doing the comparison in BigDecimalComparator - if we 
have null then the input byte array conversion to BigDecimal failed and we 
should throw an exception that explains the cause clearly - input byte array is 
too short to be a BigDecimal - and make sure the exception is handled as a 
DoNotRetryIOException in the filter layer. 

See parent issue HBASE-29672

  was:
If a scan with a filter using BigDecimalComparator encounters a row/column/byte 
array which was not encoded properly using Bytes.toBytes(BigDecimal) and is too 
short to be a BigDecimal, the scan RPC will fail with a NullPointerException, 
and the client will retry excessively until exhausting all retries, and the 
operation will fail with RetriesExhausted and a trace that looks like:
{code:java}
RetriesExhausted Failed after attempts=13, exceptions:
2025-10-20T19:31:23.525Z, java.io.IOException: java.io.IOException: Cannot read 
field "scale" because "val" is null
        at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:525)
        at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:124)
        at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:102)
        at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:82)
Caused by: java.lang.NullPointerException: Cannot read field "scale" because 
"val" is null
        at java.base/java.math.BigDecimal.compareTo(BigDecimal.java:3124)
        at 
org.apache.hadoop.hbase.filter.BigDecimalComparator.compareTo(BigDecimalComparator.java:72)
        at 
org.apache.hadoop.hbase.PrivateCellUtil.compareValue(PrivateCellUtil.java:1341)
        at 
org.apache.hadoop.hbase.filter.ColumnValueFilter.compareValue(ColumnValueFilter.java:128)
        at 
org.apache.hadoop.hbase.filter.ColumnValueFilter.filterCell(ColumnValueFilter.java:111)
        at 
org.apache.hadoop.hbase.regionserver.querymatcher.UserScanQueryMatcher.matchColumn(UserScanQueryMatcher.java:166)
        at 
org.apache.hadoop.hbase.regionserver.querymatcher.NormalUserScanQueryMatcher.match(NormalUserScanQueryMatcher.java:80)
        at 
org.apache.hadoop.hbase.regionserver.StoreScanner.next(StoreScanner.java:653)
        at 
org.apache.hadoop.hbase.regionserver.KeyValueHeap.next(KeyValueHeap.java:153)
        at 
org.apache.hadoop.hbase.regionserver.RegionScannerImpl.populateResult(RegionScannerImpl.java:348)
        at 
org.apache.hadoop.hbase.regionserver.RegionScannerImpl.nextInternal(RegionScannerImpl.java:520)
        at 
org.apache.hadoop.hbase.regionserver.RegionScannerImpl.nextRaw(RegionScannerImpl.java:285)
        at 
org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(RSRpcServices.java:3430)
        at 
org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(RSRpcServices.java:3703)
        at 
org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:45423)
        at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:458)
        ... 3 more
2025-10-20T19:31:23.645Z, java.io.IOException: java.io.IOException: Cannot read 
field "scale" because "val" is null
... {code}
+Root cause+ 
BigDecimalComparator#compareTo relies on ByteBufferUtils.toBigDecimal to 
convert the input byte array to BigDecimal, and ByteBufferUtils.toBigDecimal 
will return null if the byte array is too short. We don’t do a null check 
before doing the comparison , which leads to a NullPointerException that 
bubbles up the region server call stack which the client will treat as 
retryable exception

+Proposed solution+ 
Add a null check before doing the comparison in BigDecimalComparator - if we 
have null then the input byte array conversion to BigDecimal failed and we 
should throw an exception that explains the cause clearly - input byte array is 
too short to be a BigDecimal - and make sure the exception is handled as a 
DoNotRetryIOException in the filter layer. 

See parent issue 


> Filtering with BigDecimalComparator can fail non-gracefully with 
> NullPointerException
> -------------------------------------------------------------------------------------
>
>                 Key: HBASE-29678
>                 URL: https://issues.apache.org/jira/browse/HBASE-29678
>             Project: HBase
>          Issue Type: Bug
>          Components: Filters
>            Reporter: Daniel Roudnitsky
>            Assignee: Daniel Roudnitsky
>            Priority: Major
>
> If a scan with a filter using BigDecimalComparator encounters a 
> row/column/byte array which was not encoded properly using 
> Bytes.toBytes(BigDecimal) and is too short to be a BigDecimal, the scan RPC 
> will fail with a NullPointerException, and the client will retry excessively 
> until exhausting all retries, and the operation will fail with 
> RetriesExhausted and a trace that looks like:
> {code:java}
> RetriesExhausted Failed after attempts=13, exceptions:
> 2025-10-20T19:31:23.525Z, java.io.IOException: java.io.IOException: Cannot 
> read field "scale" because "val" is null
>       at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:525)
>       at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:124)
>       at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:102)
>       at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:82)
> Caused by: java.lang.NullPointerException: Cannot read field "scale" because 
> "val" is null
>       at java.base/java.math.BigDecimal.compareTo(BigDecimal.java:3124)
>       at 
> org.apache.hadoop.hbase.filter.BigDecimalComparator.compareTo(BigDecimalComparator.java:72)
>       at 
> org.apache.hadoop.hbase.PrivateCellUtil.compareValue(PrivateCellUtil.java:1341)
>       at 
> org.apache.hadoop.hbase.filter.ColumnValueFilter.compareValue(ColumnValueFilter.java:128)
>       at 
> org.apache.hadoop.hbase.filter.ColumnValueFilter.filterCell(ColumnValueFilter.java:111)
>       at 
> org.apache.hadoop.hbase.regionserver.querymatcher.UserScanQueryMatcher.matchColumn(UserScanQueryMatcher.java:166)
>       at 
> org.apache.hadoop.hbase.regionserver.querymatcher.NormalUserScanQueryMatcher.match(NormalUserScanQueryMatcher.java:80)
>       at 
> org.apache.hadoop.hbase.regionserver.StoreScanner.next(StoreScanner.java:653)
>       at 
> org.apache.hadoop.hbase.regionserver.KeyValueHeap.next(KeyValueHeap.java:153)
>       at 
> org.apache.hadoop.hbase.regionserver.RegionScannerImpl.populateResult(RegionScannerImpl.java:348)
>       at 
> org.apache.hadoop.hbase.regionserver.RegionScannerImpl.nextInternal(RegionScannerImpl.java:520)
>       at 
> org.apache.hadoop.hbase.regionserver.RegionScannerImpl.nextRaw(RegionScannerImpl.java:285)
>       at 
> org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(RSRpcServices.java:3430)
>       at 
> org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(RSRpcServices.java:3703)
>       at 
> org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:45423)
>       at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:458)
>       ... 3 more
> 2025-10-20T19:31:23.645Z, java.io.IOException: java.io.IOException: Cannot 
> read field "scale" because "val" is null
> ... {code}
> +Root cause+ 
> BigDecimalComparator#compareTo relies on ByteBufferUtils.toBigDecimal to 
> convert the input byte array to BigDecimal, and ByteBufferUtils.toBigDecimal 
> will return null if the byte array is too short. We don’t do a null check 
> before doing the comparison , which leads to a NullPointerException that 
> bubbles up the region server call stack which the client will treat as 
> retryable exception
> +Proposed solution+ 
> Add a null check before doing the comparison in BigDecimalComparator - if we 
> have null then the input byte array conversion to BigDecimal failed and we 
> should throw an exception that explains the cause clearly - input byte array 
> is too short to be a BigDecimal - and make sure the exception is handled as a 
> DoNotRetryIOException in the filter layer. 
> See parent issue HBASE-29672



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to