feat(api): sanitize HTTP API error responses - #6954
Open
halibobo1205 wants to merge 1 commit into
Open
Conversation
Standard HTTP error paths used to expose internal details to clients:
Util.processError prefixed every message with the Java exception class
name, several servlets printed raw Throwable.getMessage() directly, and
the two solidity query endpoints returned bare-text error bodies.
Centralize the client-facing text decision in Util.processError:
* keep the raw non-blank message only for the exact runtime types
JsonFormat.ParseException, ContractValidateException and
MaintenanceUnavailableException; a null, empty or whitespace-only
message falls back to "internal server error"
* preserve the events-deprecation message only for the exact
IllegalArgumentException type carrying EVENTS_DEPRECATED_MSG
* write the fixed rate-limit and INVALID address messages, along with
existing GetBlock validation messages, through the package-private
writeAuditedError helper; these audited callers bypass exception
classification, and printErrorMsg is private to the shared writer
* return {"Error":"internal server error"} for every other exception,
with no exception class name
Client-visible changes:
* all processError-based error bodies lose the "class <FQCN> : "
prefix; unclassified raw messages become "internal server error"
* the rate-limit rejection body becomes
{"Error":"lack of computing resources"} on every endpoint extending
RateLimiterServlet, including full-node, solidity and PBFT /jsonrpc
* gettransactionbyid / gettransactioninfobyid on solidity return
standard {"Error":...} JSON instead of bare text
* validateaddress, getBrokerage and getReward replace leaked library
messages in their failure branches with existing fixed texts; the
"INVALID address" body is now written via writeAuditedError and loses
the space after the colon
* getblock keeps its exact error bodies (refactor only)
Cover Solidity transaction and transaction-info GET/POST input errors,
backend failures, successful lookups and missing records directly with
mocked Wallet calls and in-memory requests and responses. Replace the
transaction servlet tests that accidentally exercised POST in both cases,
changed global stdout and used a shared temporary response file.
Verify both endpoint and global rate-limit rejections across the three
JSON-RPC servlet variants, including status, response body and the absence
of business dispatch on rejection.
HTTP status codes, success responses, request validation rules and
gRPC behavior are unchanged. JSON-RPC behavior is unchanged except for
the shared HTTP rate-limit response described above.
Closes tronprotocol#6936
github-actions
Bot
requested review from
0xbigapple,
bladehan1 and
waynercheung
September 8, 2026 11:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Routes the standard HTTP servlet error paths through a single decision point in
Util.processError, which determines the client-facing text:JsonFormat.ParseException,ContractValidateExceptionandMaintenanceUnavailableException; a null, empty or whitespace-only message falls back tointernal server error;IllegalArgumentExceptiontype carrying the audited message constant;INVALID addresstexts, plus the existing GetBlock validation texts, through a package-privateStringoverload used at four audited call sites that bypass exception classification;{"Error":"internal server error"}for every other exception, with no Java exception class name.Matching is on the exact top-level runtime type: subclasses do not inherit the compatibility exemptions, and cause chains are not unwrapped.
The two SolidityNode transaction-query endpoints also change from bare-text error bodies to standard
{"Error":...}JSON, andvalidateaddress,getBrokerageandgetRewardreplace leaked library text in their failure branches with the fixed messages they already use elsewhere.The full before/after compatibility table is in #6936.
Why are these changes required?
Standard HTTP error responses currently return Java exception class names and unaudited
Throwable.getMessage()values, for example{"Error":"class java.lang.NullPointerException : ..."}. That text gives clients nothing actionable, and it changes with JDK and dependency versions, so it is unsuitable as a long-term API contract; the failure-response format is inconsistent across the API.This PR has been tested by:
Follow up
Extra details
frameworkHTTP servlet layer. No gRPC or JSON-RPC code is modified. The only JSON-RPC-visible change is the shared rate-limit rejection body, which all three JSON-RPC servlets inherit fromRateLimiterServlet.Errorfield of the standard JSON body instead and treat unknown server errors asinternal server error. TheINVALID addressbody also loses the space after the colon, which affects clients matching that body literally.Closes #6936