fix: resolve OpenAPI 500 error caused by BigInt serialization in stopGracePeriodSwarm

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 #3793
This commit is contained in:
Vibe Code
2026-02-25 00:20:25 +01:00
parent 9d09e51cf7
commit d7886fb7c9
11 changed files with 38 additions and 30 deletions

View File

@@ -173,7 +173,7 @@ export const applications = pgTable("application", {
modeSwarm: json("modeSwarm").$type<ServiceModeSwarm>(),
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "number" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
ulimitsSwarm: json("ulimitsSwarm").$type<UlimitsSwarm>(),
//
@@ -367,7 +367,7 @@ const createSchema = createInsertSchema(applications, {
watchPaths: z.array(z.string()).optional(),
previewLabels: z.array(z.string()).optional(),
cleanCache: z.boolean().optional(),
stopGracePeriodSwarm: z.bigint().nullable(),
stopGracePeriodSwarm: z.number().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
ulimitsSwarm: UlimitsSwarmSchema.nullable(),
});

View File

@@ -67,7 +67,7 @@ export const mariadb = pgTable("mariadb", {
modeSwarm: json("modeSwarm").$type<ServiceModeSwarm>(),
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "number" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
ulimitsSwarm: json("ulimitsSwarm").$type<UlimitsSwarm>(),
replicas: integer("replicas").default(1).notNull(),
@@ -142,7 +142,7 @@ const createSchema = createInsertSchema(mariadb, {
modeSwarm: ServiceModeSwarmSchema.nullable(),
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
stopGracePeriodSwarm: z.number().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
ulimitsSwarm: UlimitsSwarmSchema.nullable(),
});

View File

@@ -70,7 +70,7 @@ export const mongo = pgTable("mongo", {
modeSwarm: json("modeSwarm").$type<ServiceModeSwarm>(),
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "number" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
ulimitsSwarm: json("ulimitsSwarm").$type<UlimitsSwarm>(),
replicas: integer("replicas").default(1).notNull(),
@@ -139,7 +139,7 @@ const createSchema = createInsertSchema(mongo, {
modeSwarm: ServiceModeSwarmSchema.nullable(),
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
stopGracePeriodSwarm: z.number().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
ulimitsSwarm: UlimitsSwarmSchema.nullable(),
});

View File

@@ -65,7 +65,7 @@ export const mysql = pgTable("mysql", {
modeSwarm: json("modeSwarm").$type<ServiceModeSwarm>(),
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "number" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
ulimitsSwarm: json("ulimitsSwarm").$type<UlimitsSwarm>(),
replicas: integer("replicas").default(1).notNull(),
@@ -139,7 +139,7 @@ const createSchema = createInsertSchema(mysql, {
modeSwarm: ServiceModeSwarmSchema.nullable(),
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
stopGracePeriodSwarm: z.number().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
ulimitsSwarm: UlimitsSwarmSchema.nullable(),
});

View File

@@ -65,7 +65,7 @@ export const postgres = pgTable("postgres", {
modeSwarm: json("modeSwarm").$type<ServiceModeSwarm>(),
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "number" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
ulimitsSwarm: json("ulimitsSwarm").$type<UlimitsSwarm>(),
replicas: integer("replicas").default(1).notNull(),
@@ -133,7 +133,7 @@ const createSchema = createInsertSchema(postgres, {
modeSwarm: ServiceModeSwarmSchema.nullable(),
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
stopGracePeriodSwarm: z.number().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
ulimitsSwarm: UlimitsSwarmSchema.nullable(),
});

View File

@@ -64,7 +64,7 @@ export const redis = pgTable("redis", {
modeSwarm: json("modeSwarm").$type<ServiceModeSwarm>(),
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "number" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
ulimitsSwarm: json("ulimitsSwarm").$type<UlimitsSwarm>(),
replicas: integer("replicas").default(1).notNull(),
@@ -121,7 +121,7 @@ const createSchema = createInsertSchema(redis, {
modeSwarm: ServiceModeSwarmSchema.nullable(),
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
stopGracePeriodSwarm: z.number().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
ulimitsSwarm: UlimitsSwarmSchema.nullable(),
});

View File

@@ -511,11 +511,6 @@ export const generateConfigContainer = (
ulimitsSwarm,
} = application;
const sanitizedStopGracePeriodSwarm =
typeof stopGracePeriodSwarm === "bigint"
? Number(stopGracePeriodSwarm)
: stopGracePeriodSwarm;
const haveMounts = mounts && mounts.length > 0;
return {
@@ -562,9 +557,9 @@ export const generateConfigContainer = (
Order: "start-first",
},
}),
...(sanitizedStopGracePeriodSwarm !== null &&
sanitizedStopGracePeriodSwarm !== undefined && {
StopGracePeriod: sanitizedStopGracePeriodSwarm,
...(stopGracePeriodSwarm !== null &&
stopGracePeriodSwarm !== undefined && {
StopGracePeriod: stopGracePeriodSwarm,
}),
...(networkSwarm
? {