Skip to content

feat(api): sanitize HTTP API error responses - #6954

Open
halibobo1205 wants to merge 1 commit into
tronprotocol:developfrom
halibobo1205:feature/http_error_optimization
Open

feat(api): sanitize HTTP API error responses#6954
halibobo1205 wants to merge 1 commit into
tronprotocol:developfrom
halibobo1205:feature/http_error_optimization

Conversation

@halibobo1205

Copy link
Copy Markdown
Collaborator

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:

  • keeps 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;
  • keeps the events-deprecation message, and its existing HTTP 400, only for the exact IllegalArgumentException type carrying the audited message constant;
  • writes the fixed rate-limit and INVALID address texts, plus the existing GetBlock validation texts, through a package-private String overload used at four audited call sites that bypass exception classification;
  • returns {"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, and validateaddress, getBrokerage and getReward replace 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:

  • Unit Tests

Follow up

Extra details

  • Scope is the framework HTTP 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 from RateLimiterServlet.
  • Breaking change for failure responses only, and it needs a release-notes entry: clients that parse Java exception class names, raw exception messages, or the Solidity bare-text error bodies must read the Error field of the standard JSON body instead and treat unknown server errors as internal server error. The INVALID address body also loses the space after the colon, which affects clients matching that body literally.
  • Successful responses, request parsing and validation rules, and existing HTTP status codes are unchanged.

Closes #6936

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
@halibobo1205 halibobo1205 added this to the GreatVoyage-v4.8.3 milestone Sep 8, 2026
@halibobo1205 halibobo1205 added the topic:api rpc/http related issue label Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:api rpc/http related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Standardize HTTP API Error Messages

1 participant