You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
runtime-broker: fastjson2 2.0.65 makes accepted negative-scale decimals unreadable after JDBC persistence #12859
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
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:
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.
What happened?
After #12836 aligned the Runtime Broker to fastjson2 2.0.65, the broker can accept and persist a finite negative-scale
BigDecimalthat 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
mainat302e7d88ef366991295e41dd9b158a13ab29cd74(which contains #12798 mergee471cfe6and #12836 mergefe01e228):new BigDecimal("1E+100000")hasscale() == -100000andprecision() == 1.BrokerValues.immutableMaponly rejectsscale() > 2048, soToolExecutionRecord.prepared(...)accepts this value.JdbcToolExecutionRepository.findOrCreate(...)commits the record successfully. In the H2/MySQL-compatible reproduction, the row count is 1 andreference_jsoncontains the 100001-digit plain integer written byWriteBigDecimalAsPlain.findByExecutionCallId(...)withcom.alibaba.fastjson2.JSONException: Number literal too long: 100001 digits (max 10000).The codec change is observable directly. With the same serialized JSON:
This is not an HTTP-literal bypass. On current
main, a raw request containing exponent-form1E+100000is rejected duringJsonCodec.parseObjectwith HTTP 400runtime_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/programmaticRuntimeTransportreturning aBigDecimalresult. Both reference and result values pass through the sameBrokerValues.immutableMapboundary 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 anyreference_jsonorresult_jsonwrite, 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.
QwenLM/qwen-codecurrentmainat302e7d88ef366991295e41dd9b158a13ab29cd74schema.sqlLogin 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 = 2048with a one-sideddecimal.scale() > MAXIMUM_DECIMAL_SCALEguard. 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 onmain.A minimal conservative fix is a two-sided comparison:
This avoids
Math.abs(scale)becauseInteger.MIN_VALUEwould overflow. Boundary coverage should keep1E+2048accepted, reject1E+2049, and reject anInteger.MIN_VALUEscale 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 changeBrokerValuesor address negative-scale values.Per
CONTRIBUTING.md, no implementation has been submitted before maintainer feedback on this issue.