Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix: resolve OpenAPI 500 error caused by BigInt serialization#3794

Open
vcode-sh wants to merge 1 commit intoDokploy:canaryfrom
vcode-sh:fix/openapi-bigint-serialization
Open

fix: resolve OpenAPI 500 error caused by BigInt serialization#3794
vcode-sh wants to merge 1 commit intoDokploy:canaryfrom
vcode-sh:fix/openapi-bigint-serialization

Conversation

@vcode-sh
Copy link

@vcode-sh vcode-sh commented Feb 24, 2026

What's happening

The OpenAPI endpoint /api/project.all returns a 500 Internal Server Error while the tRPC equivalent (/api/trpc/project.all) works perfectly fine. This affects any endpoint that returns services with a non-null stopGracePeriodSwarm value.

Root cause

The stopGracePeriodSwarm column across all 6 service schemas (application, mongo, mariadb, redis, mysql, postgres) uses Drizzle's bigint("...", { mode: "bigint" }), which returns JavaScript BigInt values from the database.

The tRPC route uses superjson as its transformer, which handles BigInt natively. But the OpenAPI route (@dokploy/trpc-openapi) uses plain JSON.stringify() under the hood — and JSON.stringify throws a TypeError: Do not know how to serialize a BigInt when it encounters one. The error gets caught and returned as a generic 500 with no logging, making it really hard to track down.

I confirmed this on my production instance — one of my services has stopGracePeriodSwarm: 65000000000 (65s), and the superjson metadata in the tRPC response explicitly marks it as ["bigint"].

The fix

Changed the Drizzle column mode from "bigint" to "number" for stopGracePeriodSwarm across all 6 service schemas. This is a JS-only change — the database column stays as bigint, no migration needed. The values are nanosecond grace periods that comfortably fit within Number.MAX_SAFE_INTEGER (~104 days worth of nanoseconds).

The codebase was already converting BigInt→Number everywhere it actually used the value (see generateConfigContainer in docker/utils.ts), so this just fixes it at the source instead.

Also added onError logging and export const config (with bodyParser: false and sizeLimit: "1gb") to the OpenAPI route handler to match the tRPC route — so future errors won't be completely silent.

Changes

Schema (6 files): bigint("stopGracePeriodSwarm", { mode: "bigint" }){ mode: "number" }, z.bigint().nullable()z.number().nullable()

Backend: Removed the now-unnecessary BigInt→Number conversion in docker/utils.ts

Frontend: Updated type guards and form handling in the stop grace period components to use number instead of bigint

OpenAPI handler: Added onError callback + export const config to pages/api/[...trpc].ts

Tests: Updated mechanizeDockerContainer test to use number values

Testing

  • TypeScript: both server and dokploy packages pass tsc --noEmit cleanly
  • Full test suite: 384/384 tests pass (the 4 pre-existing failures in application.real.test.ts are unrelated — they require nixpacks)
  • Verified the fix with a simulation: JSON.stringify succeeds with number where it threw with BigInt
  • Confirmed on production that the tRPC response contains the BigInt value that causes the crash

Fixes #3793

Greptile Summary

Changed stopGracePeriodSwarm from BigInt to number across all service schemas to fix OpenAPI 500 errors. The OpenAPI endpoint uses JSON.stringify() which doesn't handle BigInt values, while tRPC works because it uses superjson. The fix changes Drizzle's column mode from "bigint" to "number" - this is JS-only and requires no database migration since the PostgreSQL column remains bigint. Grace period values (in nanoseconds) safely fit within Number.MAX_SAFE_INTEGER.

  • Updated 6 database schemas (application, mongo, mariadb, redis, mysql, postgres) and their Zod validators
  • Removed now-redundant BigInt→Number conversion in docker/utils.ts
  • Updated frontend type guards and form handling to use number instead of bigint
  • Added error logging to OpenAPI handler for better debugging
  • Updated tests to reflect the type change

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The fix is well-targeted and addresses a critical production bug. All changes are type-consistent across the stack (schema, validation, frontend, backend). No database migration needed since only the JS serialization mode changed. The value range is mathematically safe (grace periods fit well within Number.MAX_SAFE_INTEGER). Tests pass and the changes align with existing conversion patterns in the codebase.
  • No files require special attention

Last reviewed commit: d7886fb

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

…GracePeriodSwarm

Change Drizzle column mode from "bigint" to "number" for stopGracePeriodSwarm
across all 6 service schemas. This fixes JSON.stringify failing silently in the
@dokploy/trpc-openapi adapter, which unlike the tRPC endpoint does not use
superjson and cannot serialize BigInt values.

No database migration needed — only the JS representation changes. The values
are nanosecond grace periods that fit safely within Number.MAX_SAFE_INTEGER.

Also adds onError logging and export const config to the OpenAPI route handler
to match the tRPC route and improve debuggability.

Fixes Dokploy#3793
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

11 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenAPI endpoint /api/project.all returns 500 while tRPC endpoint works

1 participant