22// import { maxDepthPlugin } from "@escape.tech/graphql-armor-max-depth";
33// import { maxTokensPlugin } from "@escape.tech/graphql-armor-max-tokens";
44
5+ import { GraphQLError } from "graphql" ;
56import { createYoga } from "graphql-yoga" ;
7+ import { ZodError } from "zod/v4" ;
68
79import { makeLogger } from "@/lib/logger" ;
810import { context } from "@/omnigraph-api/context" ;
911import { schema } from "@/omnigraph-api/schema" ;
1012
1113const logger = makeLogger ( "omnigraph" ) ;
1214
15+ // tests exact ZodError or GraphQLError-wrapped ZodError
16+ const isZodError = ( value : unknown ) : boolean =>
17+ value instanceof ZodError ||
18+ ( value instanceof GraphQLError && value . originalError instanceof ZodError ) ;
19+
20+ // Yoga logs every execution error (including GraphQL input validation errors) at `error` level, but
21+ // those validation errors are expected, in general, so we downgrade them to `debug` so server logs
22+ // aren't flooded with stack traces.
23+ const yogaLogger = {
24+ debug : logger . debug . bind ( logger ) ,
25+ info : logger . info . bind ( logger ) ,
26+ warn : logger . warn . bind ( logger ) ,
27+ error : ( err : unknown , ..._rest : unknown [ ] ) => {
28+ if ( isZodError ( err ) ) {
29+ logger . debug ( { err } , "GraphQL input validation rejected" ) ;
30+ return ;
31+ }
32+ logger . error ( { err } , "GraphQL execution error" ) ;
33+ } ,
34+ } ;
35+
1336export const yoga = createYoga ( {
1437 graphqlEndpoint : "*" ,
1538 schema,
@@ -36,7 +59,7 @@ export const yoga = createYoga({
3659 } ,
3760
3861 // integrate logging with pino
39- logging : logger ,
62+ logging : yogaLogger ,
4063
4164 plugins : [
4265 // TODO: plugins
0 commit comments