You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@hbase.apache.org by "Daniel Roudnitsky (Jira)" <ji...@apache.org> on 2025/10/20 20:35:00 UTC

[jira] [Updated] (HBASE-29678) Filtering with BigDecimalComparator can fail non-gracefully with NullPointerException

     [ 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)