Dockerized Next.JS Error [TRPCClientError] INTERNAL_SERVER_ERROR
Env: Docker | Node 22 | Next.JS | pnpm
Everything works fine outside of docker, I can create the build and start it in the same way, but it seems to break when run inside docker
❯ docker run -p 3000:3000 my-nextjs-app
   ▲ Next.js 15.0.2
   - Local:        http://localhost:3000
   - Network:      http://0.0.0.0:3000
 ✓ Starting...
 ✓ Ready in 242ms
[TRPC] interest.getStats took 41ms to execute
[Error [TRPCError]: ] {
  code: 'INTERNAL_SERVER_ERROR',
  [cause]: [AggregateError: ] { code: 'ECONNREFUSED' }
}
[TRPC] interest.getStats took 16ms to execute
 << query  #1 interest.getStats  {
  input: undefined,
  result: Error [TRPCClientError]: 
      at o.from (/app/.next/server/chunks/956.js:3:94182)
      at <unknown> (/app/.next/server/chunks/956.js:3:101075) {
    meta: {
      response: Response {
        status: 200,
        statusText: 'OK',
        headers: Headers {
          vary: 'RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch',
          'content-type': 'application/json',
          'transfer-encoding': 'chunked',
          date: 'Fri, 08 Nov 2024 03:33:10 GMT',
          connection: 'keep-alive',
          'keep-alive': 'timeout=5'
        },
        body: ReadableStream { locked: true, state: 'readable', supportsBYOB: true },
        bodyUsed: true,
        ok: true,
        redirected: false,
        type: 'basic',
        url: 'http://localhost:3000/api/trpc/interest.getStats?batch=1&input=%7B%220%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%7D'
      }
    },
    shape: { message: '', code: -32603, data: [Object] },
    data: {
      code: 'INTERNAL_SERVER_ERROR',
      httpStatus: 500,
      path: 'interest.getStats',
      zodError: null
    }
  },
  elapsedMs: 55
}
 ⨯ Error [TRPCClientError]: 
    at o.from (/app/.next/server/chunks/956.js:3:94182)
    at <unknown> (/app/.next/server/chunks/956.js:3:101075) {
  meta: [Object],
  shape: [Object],
  data: [Object],
  digest: '1300227502'
}
❯ docker run -p 3000:3000 my-nextjs-app
   ▲ Next.js 15.0.2
   - Local:        http://localhost:3000
   - Network:      http://0.0.0.0:3000
 ✓ Starting...
 ✓ Ready in 242ms
[TRPC] interest.getStats took 41ms to execute
[Error [TRPCError]: ] {
  code: 'INTERNAL_SERVER_ERROR',
  [cause]: [AggregateError: ] { code: 'ECONNREFUSED' }
}
[TRPC] interest.getStats took 16ms to execute
 << query  #1 interest.getStats  {
  input: undefined,
  result: Error [TRPCClientError]: 
      at o.from (/app/.next/server/chunks/956.js:3:94182)
      at <unknown> (/app/.next/server/chunks/956.js:3:101075) {
    meta: {
      response: Response {
        status: 200,
        statusText: 'OK',
        headers: Headers {
          vary: 'RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch',
          'content-type': 'application/json',
          'transfer-encoding': 'chunked',
          date: 'Fri, 08 Nov 2024 03:33:10 GMT',
          connection: 'keep-alive',
          'keep-alive': 'timeout=5'
        },
        body: ReadableStream { locked: true, state: 'readable', supportsBYOB: true },
        bodyUsed: true,
        ok: true,
        redirected: false,
        type: 'basic',
        url: 'http://localhost:3000/api/trpc/interest.getStats?batch=1&input=%7B%220%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%7D'
      }
    },
    shape: { message: '', code: -32603, data: [Object] },
    data: {
      code: 'INTERNAL_SERVER_ERROR',
      httpStatus: 500,
      path: 'interest.getStats',
      zodError: null
    }
  },
  elapsedMs: 55
}
 ⨯ Error [TRPCClientError]: 
    at o.from (/app/.next/server/chunks/956.js:3:94182)
    at <unknown> (/app/.next/server/chunks/956.js:3:101075) {
  meta: [Object],
  shape: [Object],
  data: [Object],
  digest: '1300227502'
}
Solution:Jump to solution
after some futher digging it might be a db issue, that being said is there any way to get more verbose logs out of these trpc endpoints?
4 Replies
Here is the Dockerfile:
This is how my react client is set up:
# Builder image
FROM node:22-alpine AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
WORKDIR /app
# First install dependencies so we can cache them
RUN apk update && apk upgrade
RUN apk add curl
COPY package.json pnpm-lock.yaml ./
FROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
FROM base AS build
# Now copy the rest of the app and build it
COPY . .
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm run build
# Production image
FROM base AS runner
# Create a non-root user
RUN addgroup -S nonroot && adduser -S nonroot -G nonroot
USER nonroot
# Copy the standalone output from the builder image
COPY --from=build --chown=nonroot:nonroot /app/.next/standalone ./
COPY --from=build --chown=nonroot:nonroot /app/public ./
COPY --from=build --chown=nonroot:nonroot /app/.next/static ./.next/
# Prepare the app for production
ENV DO_NOT_TRACK=1
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
ENV HOSTNAME="0.0.0.0"
EXPOSE 3000
# Start the app
CMD ["node", "server.js"]
# Builder image
FROM node:22-alpine AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
WORKDIR /app
# First install dependencies so we can cache them
RUN apk update && apk upgrade
RUN apk add curl
COPY package.json pnpm-lock.yaml ./
FROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
FROM base AS build
# Now copy the rest of the app and build it
COPY . .
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm run build
# Production image
FROM base AS runner
# Create a non-root user
RUN addgroup -S nonroot && adduser -S nonroot -G nonroot
USER nonroot
# Copy the standalone output from the builder image
COPY --from=build --chown=nonroot:nonroot /app/.next/standalone ./
COPY --from=build --chown=nonroot:nonroot /app/public ./
COPY --from=build --chown=nonroot:nonroot /app/.next/static ./.next/
# Prepare the app for production
ENV DO_NOT_TRACK=1
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
ENV HOSTNAME="0.0.0.0"
EXPOSE 3000
# Start the app
CMD ["node", "server.js"]
"use client";
import { QueryClientProvider, type QueryClient } from "@tanstack/react-query";
import { loggerLink, unstable_httpBatchStreamLink } from "@trpc/client";
import { createTRPCReact } from "@trpc/react-query";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import SuperJSON from "superjson";
import { type AppRouter } from "@/server/api/root";
import { createQueryClient } from "./query-client";
import {type ReactNode, useState} from "react";
let clientQueryClientSingleton: QueryClient | undefined = undefined;
const getQueryClient = () => {
  if (typeof window === "undefined") {
    // Server: always make a new query client
    return createQueryClient();
  }
  // Browser: use singleton pattern to keep the same query client
  return (clientQueryClientSingleton ??= createQueryClient());
};
export const api = createTRPCReact<AppRouter>();
/**
 * Inference helper for inputs.
 *
 * @example type HelloInput = RouterInputs['example']['hello']
 */
export type RouterInputs = inferRouterInputs<AppRouter>;
/**
 * Inference helper for outputs.
 *
 * @example type HelloOutput = RouterOutputs['example']['hello']
 */
export type RouterOutputs = inferRouterOutputs<AppRouter>;
export function TRPCReactProvider(props: { children: ReactNode }) {
  const queryClient = getQueryClient();
  const [trpcClient] = useState(() =>
    api.createClient({
      links: [
        loggerLink({
          enabled: (op) =>
            process.env.NODE_ENV === "development" ||
            (op.direction === "down" && op.result instanceof Error),
        }),
        unstable_httpBatchStreamLink({
          transformer: SuperJSON,
          url: getBaseUrl() + "/api/trpc",
          headers: () => {
            const headers = new Headers();
            headers.set("x-trpc-source", "nextjs-react");
            return headers;
          },
        }),
      ],
    })
  );
  return (
    <QueryClientProvider client={queryClient}>
      <api.Provider client={trpcClient} queryClient={queryClient}>
        {props.children}
      </api.Provider>
    </QueryClientProvider>
  );
}
function getBaseUrl() {
  if (typeof window !== "undefined") return window.location.origin;
  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
  return `http://localhost:${process.env.PORT ?? 3000}`;
}
"use client";
import { QueryClientProvider, type QueryClient } from "@tanstack/react-query";
import { loggerLink, unstable_httpBatchStreamLink } from "@trpc/client";
import { createTRPCReact } from "@trpc/react-query";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import SuperJSON from "superjson";
import { type AppRouter } from "@/server/api/root";
import { createQueryClient } from "./query-client";
import {type ReactNode, useState} from "react";
let clientQueryClientSingleton: QueryClient | undefined = undefined;
const getQueryClient = () => {
  if (typeof window === "undefined") {
    // Server: always make a new query client
    return createQueryClient();
  }
  // Browser: use singleton pattern to keep the same query client
  return (clientQueryClientSingleton ??= createQueryClient());
};
export const api = createTRPCReact<AppRouter>();
/**
 * Inference helper for inputs.
 *
 * @example type HelloInput = RouterInputs['example']['hello']
 */
export type RouterInputs = inferRouterInputs<AppRouter>;
/**
 * Inference helper for outputs.
 *
 * @example type HelloOutput = RouterOutputs['example']['hello']
 */
export type RouterOutputs = inferRouterOutputs<AppRouter>;
export function TRPCReactProvider(props: { children: ReactNode }) {
  const queryClient = getQueryClient();
  const [trpcClient] = useState(() =>
    api.createClient({
      links: [
        loggerLink({
          enabled: (op) =>
            process.env.NODE_ENV === "development" ||
            (op.direction === "down" && op.result instanceof Error),
        }),
        unstable_httpBatchStreamLink({
          transformer: SuperJSON,
          url: getBaseUrl() + "/api/trpc",
          headers: () => {
            const headers = new Headers();
            headers.set("x-trpc-source", "nextjs-react");
            return headers;
          },
        }),
      ],
    })
  );
  return (
    <QueryClientProvider client={queryClient}>
      <api.Provider client={trpcClient} queryClient={queryClient}>
        {props.children}
      </api.Provider>
    </QueryClientProvider>
  );
}
function getBaseUrl() {
  if (typeof window !== "undefined") return window.location.origin;
  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
  return `http://localhost:${process.env.PORT ?? 3000}`;
}
Solution
after some futher digging it might be a db issue, that being said is there any way to get more verbose logs out of these trpc endpoints?
Hello @Aerilym, have solved this issue?
hey yes all good, was an issue with the database