From 9bca50787f97e18b1b2f5a5c0bfa3681c8508422 Mon Sep 17 00:00:00 2001 From: davidercruz Date: Thu, 14 May 2026 16:48:26 +0100 Subject: [PATCH 1/3] chore(persona-quiz): log resolver failures explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both `personaQuizReveal` and `personaQuizNextQuestion` re-throw caught errors and relied on the GraphQL middleware's generic "unexpected graphql error" entry. That entry doesn't tag the resolver name, so filtering for "personaQuizReveal request failed" returned nothing during the recent on-call investigation. Add resolver-scoped `logger.warn` calls in both catch blocks. Also flag the silent "bragi returned OK but reveal is empty" case in `personaQuizReveal` — without this the frontend falls back to the seed-tag headline and the root cause is invisible from server logs. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/schema/users.ts | 48 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/schema/users.ts b/src/schema/users.ts index dc67076ec3..6005c69376 100644 --- a/src/schema/users.ts +++ b/src/schema/users.ts @@ -4588,6 +4588,16 @@ export const resolvers: IResolvers = { }, }; } catch (err) { + logger.warn( + { + err, + userId: ctx.userId, + askedCount: parsed.askedCount, + seedTagCount: parsed.seedTags.length, + priorAnswerCount: parsed.priorAnswers.length, + }, + 'personaQuizNextQuestion: request failed', + ); if (err instanceof HttpError) { throw new ServiceError({ message: 'personaQuizNextQuestion request failed', @@ -4616,6 +4626,26 @@ export const resolvers: IResolvers = { }), ); + // Surface unexpected bragi responses (success status but empty + // reveal copy) — without this log the frontend silently falls back + // to the seed-tag headline and the root cause stays invisible. + const bragiHasReveal = !!( + bragiResp.reveal && + (bragiResp.reveal.headline || bragiResp.reveal.description) + ); + if (!bragiHasReveal) { + logger.warn( + { + userId: ctx.userId, + bragiId: bragiResp.id, + includeTagCount: bragiResp.includeTags?.length ?? 0, + answerCount: parsed.answers.length, + seedTagCount: parsed.seedTags.length, + }, + 'personaQuizReveal: bragi returned empty reveal', + ); + } + // Fetch recsys-grounded fillers in parallel-friendly fashion. Used to // pad the LLM tag list up to targetCount once we've filtered through // the canonical Keyword table. @@ -4661,14 +4691,26 @@ export const resolvers: IResolvers = { return { includeTags: canonical.slice(0, parsed.targetCount), - reveal: bragiResp.reveal + reveal: bragiHasReveal ? { - headline: bragiResp.reveal.headline, - description: bragiResp.reveal.description, + headline: bragiResp.reveal!.headline, + description: bragiResp.reveal!.description, } : null, }; } catch (err) { + // Log the failure explicitly — the GraphQL middleware will also + // log a generic "unexpected graphql error" further up, but having + // a resolver-tagged entry makes it greppable by feature name. + logger.warn( + { + err, + userId: ctx.userId, + answerCount: parsed.answers.length, + seedTagCount: parsed.seedTags.length, + }, + 'personaQuizReveal: request failed', + ); if (err instanceof HttpError) { throw new ServiceError({ message: 'personaQuizReveal request failed', From 939233c862e8fe99e16d3b3032b57f444c68450b Mon Sep 17 00:00:00 2001 From: davidercruz Date: Thu, 14 May 2026 17:04:19 +0100 Subject: [PATCH 2/3] chore: trigger ci rerun Co-Authored-By: Claude Opus 4.7 (1M context) From 10d5d9264b94b2ed13dc3d232a56a4efb367bf30 Mon Sep 17 00:00:00 2001 From: davidercruz Date: Thu, 14 May 2026 17:18:27 +0100 Subject: [PATCH 3/3] chore: trigger ci rerun Co-Authored-By: Claude Opus 4.7 (1M context)