-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Precision loss when using increment/decrement with large Decimal values #29160
Description
Bug description
Bug description
When using increment or decrement operations on Decimal fields with large values (>10^18), Prisma appears to lose precision, resulting in incorrect calculated values. Manual calculation using Decimal operations works correctly.
Additional context
This appears to be a type coercion or floating-point conversion issue within Prisma's increment/decrement operations. The database field is defined as Decimal(30, 0) which should support arbitrary precision, but the increment/decrement operations seem to be losing precision with values larger than JavaScript's safe integer range (2^53 - 1).
This is critical for financial applications, blockchain applications, or any use case requiring precise arithmetic with large numbers.
Severity
🚨 Critical: Data loss, app crash, security issue
Reproduction
How to reproduce
- Define a schema with a large Decimal field:
model AssetAccount {
id Int @id @default(autoincrement())
assetId Int
address String
amount Decimal @default(0) @db.Decimal(30, 0)
@@unique([assetId, address])
}
model AssetHistory {
id Int @id @default(autoincrement())
assetId Int
address String
amount Decimal @default(0) @db.Decimal(30, 0)
totalAmount Decimal @default(0) @db.Decimal(30, 0)
// ... other fields
}- Perform sequential increment/decrement operations:
// Initial deposit
const account1 = await prisma.assetAccount.update({
where: { assetId_address: { assetId: 1, address: "0xabc..." } },
data: { amount: { increment: new Decimal("5000000000000000000000000000") } }
});
// Result: 5000000000000000000000000000 ✅
// First withdrawal
const account2 = await prisma.assetAccount.update({
where: { assetId_address: { assetId: 1, address: "0xabc..." } },
data: { amount: { decrement: new Decimal("1000000000000000000000") } }
});
// Result: 4999999000000000000000000000 ✅
// Second withdrawal
const account3 = await prisma.assetAccount.update({
where: { assetId_address: { assetId: 1, address: "0xabc..." } },
data: { amount: { decrement: new Decimal("1000000000000000000000") } }
});
// Expected: 4999998000000000000000000000
// Actual: 4999997999999999000000000000 ❌ (precision loss)Expected vs. Actual Behavior
Expected behavior
Each decrement of 1000000000000000000000 should subtract exactly that amount:
- Start: 5,000,000,000,000,000,000,000,000,000
- After withdrawal 1: 4,999,999,000,000,000,000,000,000,000
- After withdrawal 2: 4,999,998,000,000,000,000,000,000,000
- After withdrawal 3: 4,999,997,000,000,000,000,000,000,000
Actual behavior
Precision is lost on subsequent operations:
- Start: 5,000,000,000,000,000,000,000,000,000
- After withdrawal 1: 4,999,999,000,000,000,000,000,000,000
- After withdrawal 2: 4,999,997,999,999,999,000,000,000,000 ❌
- After withdrawal 3: 4,999,996,999,999,999,000,000,000,000 ❌
Frequency
Consistently reproducible
Does this occur in development or production?
Both development and production
Is this a regression?
No
Workaround
Manual calculation works correctly:
const account = await prisma.assetAccount.findUnique({
where: { assetId_address: { assetId: 1, address: "0xabc..." } }
});
const newAmount = new Decimal(account.amount).sub(decrementValue);
const updated = await prisma.assetAccount.update({
where: { assetId_address: { assetId: 1, address: "0xabc..." } },
data: { amount: newAmount }
});Prisma Schema & Queries
// Add relevant schema.prisma snippet// Add relevant Prisma Client queryPrisma Config
// Add your `prisma.config.ts`Logs & Debug Info
// Debug logs here
Environment & Setup
Environment & setup
Prisma Version:
prisma : 7.3.0
@prisma/client : 7.3.0
Database:
- PostgreSQL (version: )
- MySQL (version:8.0.40 )
- Other:
Operating System:
- macOS
- Windows
- Linux
Node.js version:
v24.13.0
Prisma Version
prisma : 7.3.0
@prisma/client : 7.3.0
Operating System : darwin
Architecture : arm64
Node.js : v24.13.0
TypeScript : 5.9.3
Query Compiler : enabled
PSL : @prisma/prisma-schema-wasm 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
Schema Engine : schema-engine-cli 9d6ad21cbbceab97458517b147a6a09ff43aa735 (at node_modules/@prisma/engines/schema-engine-darwin-arm64)
Default Engines Hash : 9d6ad21cbbceab97458517b147a6a09ff43aa735
Studio : 0.13.1