Skip to content

runtime-broker: fastjson2 2.0.65 makes accepted negative-scale decimals unreadable after JDBC persistence #12859

Description

@yc2bgr8

What happened?

After #12836 aligned the Runtime Broker to fastjson2 2.0.65, the broker can accept and persist a finite negative-scale BigDecimal that the same codec can no longer read back. This recreates the unreadable-row invariant that #12798 closed on the positive-scale side, through a version-specific integer-side limit.

Verified on current main at 302e7d88ef366991295e41dd9b158a13ab29cd74 (which contains #12798 merge e471cfe6 and #12836 merge fe01e228):

  • new BigDecimal("1E+100000") has scale() == -100000 and precision() == 1.
  • BrokerValues.immutableMap only rejects scale() > 2048, so ToolExecutionRecord.prepared(...) accepts this value.
  • JdbcToolExecutionRepository.findOrCreate(...) commits the record successfully. In the H2/MySQL-compatible reproduction, the row count is 1 and reference_json contains the 100001-digit plain integer written by WriteBigDecimalAsPlain.
  • A fresh repository instance then fails in findByExecutionCallId(...) with com.alibaba.fastjson2.JSONException: Number literal too long: 100001 digits (max 10000).

The codec change is observable directly. With the same serialized JSON:

fastjson2 2.0.60 -> class=java.math.BigInteger, digits=100001, same=true
fastjson2 2.0.65 -> JSONException: Number literal too long: 100001 digits (max 10000)

This is not an HTTP-literal bypass. On current main, a raw request containing exponent-form 1E+100000 is rejected during JsonCodec.parseObject with HTTP 400 runtime_broker_invalid_json (too large exp value). The live path is a programmatic Java map: a caller of the Java service API, or a custom/programmatic RuntimeTransport returning a BigDecimal result. Both reference and result values pass through the same BrokerValues.immutableMap boundary before JDBC persistence.

What did you expect to happen?

Every JSON value accepted at the broker's shared value boundary must remain readable after persistence. If the pinned codec cannot round-trip a negative-scale BigDecimal, the broker should reject it before any reference_json or result_json write, just as it already rejects positive scales above 2048.

Client information

Client Information

This is a Java Runtime Broker library reproduction, not an interactive CLI session.

  • Repository: QwenLM/qwen-code current main at 302e7d88ef366991295e41dd9b158a13ab29cd74
  • Codec: fastjson2 2.0.65, as merged by chore(sdk-java): align fastjson2 version to 2.0.65 #12836
  • Database: in-memory H2 2.3.232 in MySQL compatibility mode, initialized from the production schema.sql
  • Java: OpenJDK 25.0.2
  • Platform: Windows 11 x64

Login information

Not applicable. The defect is entirely inside the Java Runtime Broker value-validation and JDBC serialization path.

Anything else we need to know?

The current positive boundary came from #12798: MAXIMUM_DECIMAL_SCALE = 2048 with a one-sided decimal.scale() > MAXIMUM_DECIMAL_SCALE guard. During that PR's real-environment verification, fastjson2 2.0.65 was already identified as introducing the integer-side unreadable-row case; it was not a problem under the then-pinned 2.0.60 and was therefore correctly left as a follow-up. #12836 has now made that follow-up live on main.

A minimal conservative fix is a two-sided comparison:

decimal.scale() > MAXIMUM_DECIMAL_SCALE
        || decimal.scale() < -MAXIMUM_DECIMAL_SCALE

This avoids Math.abs(scale) because Integer.MIN_VALUE would overflow. Boundary coverage should keep 1E+2048 accepted, reject 1E+2049, and reject an Integer.MIN_VALUE scale before serialization. The 2048 negative bound is conservative relative to fastjson2 2.0.65's 10000-digit reader limit, but it preserves the single symmetric persistence contract already documented for positive scale and fails closed across codec changes.

Duplicate checks covered open and closed Issues/PRs for 1E+100000, Number literal too long, negative scale, fastjson2, JDBC and Runtime Broker. The only matching records are #12796/#12798 and their review evidence; no separate implementation exists. Open PRs #12839 and #12848 touch adjacent Runtime Broker/JDBC tests for different features but do not change BrokerValues or address negative-scale values.

Per CONTRIBUTING.md, no implementation has been submitted before maintainer feedback on this issue.

Activity

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

Metadata

Metadata

Assignees

Labels

category/coreCore engine and logicpriority/P2Medium - Moderately impactful, noticeable problemscope/sdktype/bugSomething isn't working as expected

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions