Skip to content

[BUG] Instance information is double-encoded by WebSocket and HTTP sync reporting #7716

Open

Description

@Aias00

Current behavior

The WebSocket client places SystemInfoUtils.getSystemInfo() (an already serialized JSON string) inside its report. Admin extracts that string and serializes it again for instanceInfo. HTTP long polling likewise reads JSON from a header and calls toJson on the string. Independent heartbeat reports carry the original JSON string directly.

Consequently the instanceInfo field has incompatible encodings across reporting channels. Parsing it once yields a string on the sync paths and an object on the direct path; the dashboard's one-pass JSON formatting displays escaped JSON rather than consistent structured information.

Evidence

Acceptance criteria

  • Define one JSON encoding contract for the instance information field across all three reporting channels.
  • Normalize once at a shared boundary or fix the producers/receivers consistently; avoid heuristic decoding loops.
  • Define compatibility for already persisted double-encoded values and older reporters.
  • Test equivalent information through WebSocket, HTTP sync and independent heartbeat, including missing/malformed information and dashboard rendering.
  • Preserve liveness reporting if optional information is invalid; expose diagnostics without logging sensitive payloads.

Related: #7692 concerns metadata refresh and #7696 concerns type identity; neither fixes encoding.

Source-inspection finding; no runtime reproduction was run during issue preparation.

Activity

  1. laomo-hub commented on Oct 17, 2026

    @laomo-hub
    Contributor

    Hi, I'd like to work on this issue.

    I reproduced the HTTP double encoding and legacy stored/heartbeat values, and checked the WebSocket path with executable regressions. The ordinary WebSocket case already passes because convertToMap recursively parses JSON-looking strings; that recursion instead changes nested string values. The proposed contract keeps instanceInfo as a string containing a JSON object, so consumers can parse it once without changing nested values.

    The local patch removes HTTP re-encoding, extracts WebSocket metadata without recursive conversion, normalizes optional information at the shared heartbeat boundary, and normalizes one known legacy string-wrapped object representation when reading stored records. Missing/invalid optional information falls back to {} without stopping heartbeat processing. The original regression run reports 5 cases, 4 failures and the ordinary WebSocket control passing; all 132 targeted cases pass after the patch, including H2 legacy-read coverage. Admin and its 28-project prerequisite reactor also pass clean verify (2,741 reported tests, 2 skipped, no failures/errors), including Checkstyle and RAT.

    Please let me know if this overlaps with existing work or if there are compatibility requirements I should account for.

  2. Aias00 commented on Oct 18, 2026

    @Aias00
    ContributorAuthor

    Hi, I'd like to work on this issue.

    I reproduced the HTTP double encoding and legacy stored/heartbeat values, and checked the WebSocket path with executable regressions. The ordinary WebSocket case already passes because convertToMap recursively parses JSON-looking strings; that recursion instead changes nested string values. The proposed contract keeps instanceInfo as a string containing a JSON object, so consumers can parse it once without changing nested values.

    The local patch removes HTTP re-encoding, extracts WebSocket metadata without recursive conversion, normalizes optional information at the shared heartbeat boundary, and normalizes one known legacy string-wrapped object representation when reading stored records. Missing/invalid optional information falls back to {} without stopping heartbeat processing. The original regression run reports 5 cases, 4 failures and the ordinary WebSocket control passing; all 132 targeted cases pass after the patch, including H2 legacy-read coverage. Admin and its 28-project prerequisite reactor also pass clean verify (2,741 reported tests, 2 skipped, no failures/errors), including Checkstyle and RAT.

    Please let me know if this overlaps with existing work or if there are compatibility requirements I should account for.

    comment /assign

  3. added a commit that references this issue on Oct 19, 2026
  4. laomo-hub commented on Nov 4, 2026

    @laomo-hub
    Contributor

    Hi, I checked this locally after #7785 was merged, using ShenYu master (585f99da) and Dashboard master (5a9e5ae0).

    I ran separate gateways using WebSocket and HTTP sync. In both cases, the instance information appeared as a JSON object in the Dashboard, without the extra string wrapper.

    I also sent normal, legacy-wrapped, missing, malformed, and non-object values to the heartbeat endpoint. The legacy value was displayed as an object, including a nested JSON-looking string that stayed a string. Missing or invalid values fell back to {}, and the heartbeat requests were accepted.

    These legacy and invalid values were sent as test heartbeats; I didn't test an existing double-encoded database row or a mixed-version deployment in this run. #7785 has an H2 regression test for reading an existing legacy row.

    Is there anything else you'd like me to check, and would it be okay to close this issue? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions