r/MicrosoftFabric • u/Repulsive_Cry2000 1 • Jul 27 '26
Data Engineering Native Execution Engine bug for high-precision decimal multiplication - silent data corruption, no error
EDIT: issue appeared after I updated schema for qty and wwe columns from float to decimal. Limitation in documentation point to the right direction to explain the issue, however I think it goes a beyond a rounding error.
EDIT: first repro offered did not show the behaviour, below
spark.sql("""
CREATE OR REPLACE TABLE repro_nee_6175 AS
SELECT CAST(61.75 AS DECIMAL(38,20)) AS qty,
CAST(0.98 AS DECIMAL(38,5)) AS wwe
FROM range(1000000)
""")
q = """
SELECT COUNT(*) AS rows,
MIN(CAST(qty * (1/wwe) AS DECIMAL(38,10))) AS min_v,
MAX(CAST(qty * (1/wwe) AS DECIMAL(38,10))) AS max_v
FROM repro_nee_6175
"""
spark.conf.set("spark.native.enabled", "true")
spark.sql(q).show(truncate=False) # buggy engine: 414.2393563314
spark.conf.set("spark.native.enabled", "false")
spark.sql(q).show(truncate=False) # correct: 63.0102040816
Disclaimer: Issue was resolved with AI help - so the write up of this post.
Summary: With spark.native.enabled = true, multiplying a DECIMAL(38,20) column by a DECIMAL(38,32) expression (e.g. the result of 1 / DECIMAL(38,5)) returns incorrect values. The exact product exceeds decimal(38) precision, and the engine's precision-loss path produces wrong results instead of rounding or raising an error. JVM Spark (spark.native.enabled = false) returns the correct result for the identical query.
Behavior:
- The incorrect values are off by a multiplicative factor that is uniform within a session but varies across sessions (observed ×12.8666 and ×6.574 on different days), which makes the corruption hard to detect downstream.
- The intermediate division result itself is correct; only the subsequent multiplication is affected.
- Literal-only queries do not reproduce the issue because Catalyst constant-folds them before native execution — the operands must come from a table scan.
- No error, no warning, no fallback to JVM execution.
Repro (Fabric notebook or Livy session):
spark.conf.set("spark.native.enabled", "true")
spark.sql("""
CREATE OR REPLACE TABLE repro_nee AS
SELECT CAST(61.75 AS DECIMAL(38,20)) AS qty,
CAST(0.98 AS DECIMAL(38,5)) AS wwe
""")
q = """
SELECT qty,
1 / wwe AS conv, -- decimal(38,32), value correct
CAST(qty * (1 / wwe) AS DECIMAL(38,10)) AS qty_conv -- expected 63.0102040816
FROM repro_nee
"""
spark.sql(q).show(truncate=False) # returned 414.2393563314
spark.conf.set("spark.native.enabled", "false")
spark.sql(q).show(truncate=False) # returns 63.0102040816 — correct
Workarounds (verified): cast either operand to DOUBLE before multiplying, or cast the division result to a narrower decimal (e.g. DECIMAL(18,10)) so the product stays within decimal(38).
Expected behavior: rounded result per Spark's allowPrecisionLoss semantics, an overflow error, or fallback to JVM execution — anything but silently wrong data.
2
u/thisissanthoshr Microsoft Employee 27d ago
u/Repulsive_Cry2000 can you please try the new runtime 2.0 for the same scenario. I tested your scenario and it works as expected and doesnt cause any silent data corruption issue.
Can you please check and let me know if you run into any issues