Как понять, что проблема в проекте связана с tRPC, а не с API, сетью, дизайном состояния или плохой архитектурой?
Диагностику начинают с изоляции: если прямой fetch к /api/trpc воспроизводит проблему — виноват сервер или сеть; если только в UI — проблема в клиенте, кэше или компоненте. tRPC редко является первопричиной.
Принцип диагностики: изоляция слоёв
tRPC — тонкая транспортная обёртка. Большинство проблем, которые кажутся «проблемами tRPC», на самом деле в одном из пяти слоёв: сеть, сервер (бизнес-логика), кэш (React Query), компонент (state/rendering), архитектура данных. Задача — последовательно исключать слои.
Шаг 1: Воспроизвести без клиента tRPC
Сделайте прямой HTTP-запрос к процедуре через curl или fetch в браузере:
// В консоли браузера или Node.js REPL
const res = await fetch('/api/trpc/user.getById?batch=1&input={"0":{"json":{"id":1}}}');
console.log(await res.json());
Если ответ некорректен — проблема на сервере или в сети, не в tRPC-клиенте.
Шаг 2: Изолировать React Query от tRPC
Проверьте состояние кэша через React Query DevTools:
- Какой
queryKeyиспользуется? Нет ли дублей из-за разных input-объектов? - Статус:
stale,fresh,error? Когда последний раз былfetchedAt? - Если данные есть в кэше, но компонент не отображает — проблема в компоненте, не в tRPC.
Шаг 3: Проверить серверную логику напрямую
В Next.js вызовите процедуру через createCaller в юнит-тесте или серверном компоненте, минуя HTTP:
import { createCaller } from '@/server/router';
// В test-файле или Server Action
const caller = createCaller({ session: mockSession, db: testDb });
const result = await caller.user.getById({ id: 1 });
console.log(result); // Если ошибка здесь — баг в бизнес-логике
Шаг 4: Идентифицировать специфичные баги tRPC
После исключения сети, сервера и React Query остаётся малый класс реальных проблем tRPC:
- Сериализация: tRPC использует
superjsonпо умолчанию;Date,Map,Setмогут некорректно сериализоваться, если трансформер не настроен. - Ошибки типов в runtime: несовпадение версий
AppRouterмежду клиентом и сервером при раздельном деплое. - Middleware context: если
createContextне передаёт нужные данные (session, db) — ошибка выглядит как tRPC, но это контекст.
Шаг 5: Отличить архитектурную проблему
Если несколько компонентов запрашивают одни данные и вы видите N+1 запросов — это не баг tRPC, а архитектурная проблема. Решение: useSuspenseQuery с prefetch или вынос данных в общий провайдер.
Подводные камни
- TRPCClientError vs TRPCError: клиентская ошибка приходит обёрнутой;
error.data?.codeиerror.data?.zodError— правильные поля для диагностики валидации. - Batch-запросы маскируют ошибки: если одна из 5 процедур в batch падает, остальные могут вернуть успех; нужно проверять каждый элемент ответа.
- superjson нужно регистрировать на обоих концах: transformer в
createTRPCReactи в адаптере сервера должны совпадать, иначе даты десериализуются как строки. - Context не типизирован до
createContext: ошибкаctx.session is undefined— это middleware, а не tRPC. - React Query DevTools отключены в production: добавьте временное логирование через
queryClient.getQueryCache().getAll()для prod-диагностики.
What hurts your answer
- Сразу обвинять tRPC, не проверив соседние слои системы
- Чинить симптом без минимального воспроизведения и evidence
- Не учитывать версии, конфигурацию, окружение и recent changes
What they're listening for
- Умеет локализовать проблему вокруг tRPC
- Двигается от симптома к гипотезам и проверкам
- Отличает баг инструмента от ошибки использования или окружения