Skip to content

Precision loss when using increment/decrement with large Decimal values #29160

@fri13th

Description

@fri13th

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

  1. 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
}
  1. 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 query

Prisma 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug/1-unconfirmedBug should have enough information for reproduction, but confirmation has not happened yet.kind/bugA reported bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions