Skip to content

Commit e4f7444

Browse files
authored
fix: Unsupported method handling (#2198)
* Squashed commit of the following: commit fb63065 Author: Tomelia1999 <[email protected]> Date: Wed Jan 21 13:58:54 2026 +0100 remove functionality duplication commit 37251cb Author: Tomelia1999 <[email protected]> Date: Thu Jan 15 18:32:01 2026 +0200 WIP: unsupported method - bytes comparison instead of stign comparison commit 298dce8 Author: Tomelia1999 <[email protected]> Date: Mon Jan 5 18:19:16 2026 +0200 unify functions + adding unit tests commit 057da85 Author: Tomelia1999 <[email protected]> Date: Mon Jan 5 14:54:35 2026 +0200 improve flow of unsupported method * cache response hash * adding IsUnsupportedMethod flag * do not iterate successResponse when looking for unsupported methods * fix unit test * lint * adding string a common unsupported method string for comparison * Do not check for "unsupported method" when isNodeError * lint * lint
1 parent c256fe2 commit e4f7444

17 files changed

+795
-523
lines changed

protocol/chainlib/debug_retry_test.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@ func TestSpecificErrorFromUser(t *testing.T) {
1313
// Test the specific error pattern from the user
1414
errorMsg := "rpc error: code = Unknown desc = unsupported method 'Default-/cosmos/base/tendermint/v1beta1/blocks1/2': Not Implemented"
1515

16-
// Test message detection
17-
t.Run("Message pattern detection", func(t *testing.T) {
18-
result := IsUnsupportedMethodErrorMessage(errorMsg)
19-
require.True(t, result, "Should detect 'unsupported method' in the error message")
20-
})
21-
2216
// Test with actual error
2317
t.Run("Error object detection", func(t *testing.T) {
2418
err := errors.New(errorMsg)

protocol/chainlib/jsonRPC.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -465,18 +465,6 @@ func (apil *JsonRPCChainListener) Serve(ctx context.Context, cmdFlags common.Con
465465
return addHeadersAndSendString(fiberCtx, reply.GetMetadata(), string(errorResponse))
466466
}
467467

468-
// Check if the error message indicates an unsupported method
469-
if IsUnsupportedMethodErrorMessage(err.Error()) {
470-
// Convert error to JSON string and add headers
471-
errorResponse, _ := json.Marshal(common.JsonRpcMethodNotFoundError)
472-
return addHeadersAndSendString(fiberCtx, reply.GetMetadata(), string(errorResponse))
473-
}
474-
475-
// Check if the error message indicates an unsupported method
476-
if IsUnsupportedMethodErrorMessage(err.Error()) {
477-
return fiberCtx.Status(fiber.StatusBadRequest).JSON(common.JsonRpcMethodNotFoundError)
478-
}
479-
480468
if _, ok := err.(*json.SyntaxError); ok {
481469
// Convert error to JSON string and add headers
482470
errorResponse, _ := json.Marshal(common.JsonRpcParseError)

protocol/chainlib/node_error_handler.go

Lines changed: 10 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package chainlib
22

33
import (
4-
"bytes"
54
"context"
65
"errors"
76
"fmt"
@@ -23,58 +22,6 @@ import (
2322
"github.com/lavanet/lava/v5/utils"
2423
)
2524

26-
// Error pattern constants for unsupported method detection
27-
const (
28-
// JSON-RPC error patterns
29-
JSONRPCMethodNotFound = "method not found"
30-
JSONRPCMethodNotSupported = "method not supported"
31-
JSONRPCUnknownMethod = "unknown method"
32-
JSONRPCMethodDoesNotExist = "method does not exist"
33-
JSONRPCInvalidMethod = "invalid method"
34-
JSONRPCErrorCode = "-32601" // JSON-RPC 2.0 method not found error code
35-
36-
// REST API error patterns
37-
RESTEndpointNotFound = "endpoint not found"
38-
RESTRouteNotFound = "route not found"
39-
RESTPathNotFound = "path not found"
40-
RESTMethodNotAllowed = "method not allowed"
41-
42-
// gRPC error patterns
43-
GRPCMethodNotImplemented = "method not implemented"
44-
GRPCUnimplemented = "unimplemented"
45-
GRPCNotImplemented = "not implemented"
46-
GRPCServiceNotFound = "service not found"
47-
48-
// HTTP status codes for unsupported endpoints
49-
HTTPStatusNotFound = 404
50-
HTTPStatusMethodNotAllowed = 405
51-
52-
// JSON-RPC error code for method not found
53-
JSONRPCMethodNotFoundCode = -32601
54-
)
55-
56-
// Pre-computed byte patterns for efficient matching (initialized once at package load)
57-
// These are the lowercase versions of the pattern constants above
58-
var unsupportedMethodPatternBytes = [][]byte{
59-
// JSON-RPC patterns (most common, ordered by frequency)
60-
[]byte(JSONRPCMethodNotFound), // "method not found"
61-
[]byte(JSONRPCMethodNotSupported), // "method not supported"
62-
[]byte(JSONRPCUnknownMethod), // "unknown method"
63-
[]byte(JSONRPCMethodDoesNotExist), // "method does not exist"
64-
[]byte(JSONRPCInvalidMethod), // "invalid method"
65-
[]byte(JSONRPCErrorCode), // "-32601"
66-
// REST patterns
67-
[]byte(RESTEndpointNotFound), // "endpoint not found"
68-
[]byte(RESTRouteNotFound), // "route not found"
69-
[]byte(RESTPathNotFound), // "path not found"
70-
[]byte(RESTMethodNotAllowed), // "method not allowed"
71-
// gRPC patterns
72-
[]byte(GRPCMethodNotImplemented), // "method not implemented"
73-
[]byte(GRPCUnimplemented), // "unimplemented"
74-
[]byte(GRPCNotImplemented), // "not implemented"
75-
[]byte(GRPCServiceNotFound), // "service not found"
76-
}
77-
7825
type UnsupportedMethodError struct {
7926
originalError error
8027
methodName string
@@ -110,71 +57,25 @@ func NewUnsupportedMethodError(originalError error, methodName string) *Unsuppor
11057
}
11158
}
11259

113-
// GetUnsupportedMethodPatterns returns all error patterns that indicate an unsupported method
114-
// This is useful for documentation and testing purposes
115-
func GetUnsupportedMethodPatterns() map[string][]string {
116-
return map[string][]string{
117-
"json-rpc": {
118-
JSONRPCMethodNotFound,
119-
JSONRPCMethodNotSupported,
120-
JSONRPCUnknownMethod,
121-
JSONRPCMethodDoesNotExist,
122-
JSONRPCInvalidMethod,
123-
JSONRPCErrorCode,
124-
},
125-
"rest": {
126-
RESTEndpointNotFound,
127-
RESTRouteNotFound,
128-
RESTPathNotFound,
129-
RESTMethodNotAllowed,
130-
},
131-
"grpc": {
132-
GRPCMethodNotImplemented,
133-
GRPCUnimplemented,
134-
GRPCNotImplemented,
135-
GRPCServiceNotFound,
136-
},
137-
}
138-
}
139-
140-
// IsUnsupportedMethodErrorMessage checks if an error message indicates an unsupported method
141-
// This is a convenience function that accepts a string directly
142-
func IsUnsupportedMethodErrorMessage(errorMessage string) bool {
143-
return IsUnsupportedMethodErrorMessageBytes([]byte(errorMessage))
144-
}
145-
146-
// IsUnsupportedMethodErrorMessageBytes checks if an error message (as bytes) indicates an unsupported method.
147-
// This is more efficient than IsUnsupportedMethodErrorMessage when working with []byte data
148-
// as it avoids string conversions and uses pre-computed byte patterns with a single-pass lowercase conversion.
149-
func IsUnsupportedMethodErrorMessageBytes(errorMessage []byte) bool {
150-
// Convert to lowercase once (single O(n) pass)
151-
errorMsgLower := bytes.ToLower(errorMessage)
152-
msgLen := len(errorMsgLower)
153-
154-
// Check all patterns with early exit on first match
155-
for _, pattern := range unsupportedMethodPatternBytes {
156-
if len(pattern) <= msgLen && bytes.Contains(errorMsgLower, pattern) {
157-
return true
158-
}
159-
}
160-
161-
return false
162-
}
163-
16460
// IsUnsupportedMethodError checks if an error indicates an unsupported method
61+
// This is the comprehensive check that handles:
62+
// - Error message pattern matching (via common.IsUnsupportedMethodMessage)
63+
// - HTTP status codes (404, 405)
64+
// - gRPC status codes (Unimplemented)
65+
// - JSON-RPC error codes (-32601)
16566
func IsUnsupportedMethodError(nodeError error) bool {
16667
if nodeError == nil {
16768
return false
16869
}
16970

17071
// First check the error message patterns
171-
if IsUnsupportedMethodErrorMessage(nodeError.Error()) {
72+
if common.IsUnsupportedMethodMessage(nodeError.Error()) {
17273
return true
17374
}
17475

17576
// Check for HTTP status codes that indicate unsupported endpoints
17677
if httpError, ok := nodeError.(rpcclient.HTTPError); ok {
177-
return httpError.StatusCode == HTTPStatusNotFound || httpError.StatusCode == HTTPStatusMethodNotAllowed
78+
return httpError.StatusCode == common.HTTPStatusNotFound || httpError.StatusCode == common.HTTPStatusMethodNotAllowed
17879
}
17980

18081
// Check for gRPC status codes
@@ -184,20 +85,20 @@ func IsUnsupportedMethodError(nodeError error) bool {
18485
return true
18586
}
18687
// Also check Unknown code with unsupported method message
187-
if st.Code() == codes.Unknown && IsUnsupportedMethodErrorMessage(st.Message()) {
88+
if st.Code() == codes.Unknown && common.IsUnsupportedMethodMessage(st.Message()) {
18889
return true
18990
}
19091
}
19192

19293
// Try to recover JSON-RPC error from HTTP error
19394
if jsonMsg := TryRecoverNodeErrorFromClientError(nodeError); jsonMsg != nil && jsonMsg.Error != nil {
19495
// JSON-RPC error code -32601 is "Method not found"
195-
if jsonMsg.Error.Code == JSONRPCMethodNotFoundCode {
96+
if jsonMsg.Error.Code == common.JSONRPCMethodNotFoundCode {
19697
return true
19798
}
19899
// Check error message patterns in JSON-RPC error
199100
if jsonMsg.Error.Message != "" {
200-
return IsUnsupportedMethodErrorMessage(jsonMsg.Error.Message)
101+
return common.IsUnsupportedMethodMessage(jsonMsg.Error.Message)
201102
}
202103
}
203104

0 commit comments

Comments
 (0)