Dokploy/dokploy · error · TRPCError
BAD_REQUEST
BAD_REQUEST
Error message
externalGRPCPort cannot be set when sqldNode is 'replica'
What it means
Libsql replicas sync from a primary and must not expose their own external gRPC port. The update procedure rejects the combination sqldNode === 'replica' with a non-null externalGRPCPort as BAD_REQUEST — a domain business rule, not a system failure.
Source
Thrown at apps/dokploy/server/api/routers/libsql.ts:184
await audit(ctx, {
action: "stop",
resourceType: "service",
resourceId: libsql.libsqlId,
resourceName: libsql.appName,
});
return libsql;
}),
saveExternalPorts: protectedProcedure
.input(apiSaveExternalPortsLibsql)
.mutation(async ({ input, ctx }) => {
await checkServicePermissionAndAccess(ctx, input.libsqlId, {
service: ["create"],
});
const libsql = await findLibsqlById(input.libsqlId);
if (libsql.sqldNode === "replica" && input.externalGRPCPort !== null) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "externalGRPCPort cannot be set when sqldNode is 'replica'",
});
}
const portsToCheck = [
{
port: input.externalPort,
name: "externalPort",
current: libsql.externalPort,
},
{
port: input.externalGRPCPort,
name: "externalGRPCPort",
current: libsql.externalGRPCPort,
},
{
port: input.externalAdminPort,View on GitHub (pinned to 546686ea35)
Solutions
- Set externalGRPCPort to null (or omit it) when choosing sqldNode 'replica'
- If you need the port, keep/promote the node to primary instead
- Split into two updates only if the UI requires: first clear the port, then change role
Example fix
// before
await api.libsql.update.mutate({ libsqlId, sqldNode: "replica", externalGRPCPort: 5001 });
// after
await api.libsql.update.mutate({ libsqlId, sqldNode: "replica", externalGRPCPort: null }); Defensive patterns
Strategy: validation
Validate before calling
if (sqldNode === "replica") input.externalGRPCPort = null;
Type guard
const isValidRolePortCombo = (node: string, port: number | null): boolean => node !== "replica" || port === null;
Prevention
- UI should clear/lock the gRPC port field when replica is chosen
When it happens
Trigger: Editing a database and switching its role to 'replica' while leaving an externalGRPCPort set, or explicitly sending a port for a replica.
Common situations: Migrating a standalone Libsql into a replica topology without clearing the previously assigned gRPC port in the same update.
Understand the failure class
Background: BAD_REQUEST error code: request rejected as invalid (HTTP 400) - causes and fixes across libraries — this error's family across 8 libraries.
Related errors
AI-assisted analysis of Dokploy/dokploy@546686ea35 (2026-08-27).
Data as JSON: /api/errors/6d6ef10e1895e894.
Report an issue: GitHub.