{"record":{"id":"85e7aeffa39850fb","repo":"lobehub/lobehub","slug":"internal-server-error-85e7ae","errorCode":"INTERNAL_SERVER_ERROR","errorMessage":"Failed to fetch changelog index","messagePattern":"Failed to fetch changelog index","errorType":"exception","errorClass":"TRPCError","httpStatus":500,"severity":"error","filePath":"apps/server/src/routers/lambda/changelog.ts","lineNumber":20,"sourceCode":"import { z } from 'zod';\n\nimport { publicProcedure, router } from '@/libs/trpc/lambda';\nimport { ChangelogService } from '@/server/services/changelog';\n\nconst changelogProcedure = publicProcedure.use(async ({ next }) => {\n  return next({\n    ctx: {\n      changelogService: new ChangelogService(),\n    },\n  });\n});\n\nexport const changelogRouter = router({\n  getIndex: changelogProcedure.query(async ({ ctx }) => {\n    try {\n      return await ctx.changelogService.getChangelogIndex();\n    } catch (e) {\n      throw new TRPCError({\n        code: 'INTERNAL_SERVER_ERROR',\n        message: 'Failed to fetch changelog index',\n      });\n    }\n  }),\n\n  getPostById: changelogProcedure\n    .input(\n      z.object({\n        id: z.string(),\n        locale: z.string().optional(),\n      }),\n    )\n    .query(async ({ input, ctx }) => {\n      try {\n        return await ctx.changelogService.getPostById(input.id, { locale: input.locale as any });\n      } catch (e) {\n        throw new TRPCError({","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/lobehub/lobehub/blob/10f24d7ade75139093a9373b364f6bc91f3cd7db/apps/server/src/routers/lambda/changelog.ts#L2-L38","documentation":"Catch-all for `changelog.getIndex`. `ChangelogService` is constructed with no deps and reads the changelog index (typically bundled markdown/JSON or a fetched manifest). This error means the index read failed — file missing on disk, bundling issue, or the service threw on malformed content. Note the handler does NOT log the cause, so the underlying error is harder to recover.","triggerScenarios":"Changelog index file/manifest absent in the deployed bundle, unreadable due to permissions, or its JSON frontmatter malformed. A network fetch (if the service pulls remotely) timing out.","commonSituations":"First deploy where the changelog content wasn't bundled; a content PR introduced malformed frontmatter; read-only filesystem mount failure.","solutions":["Patch the handler to log the cause (`console.error('[changelog:getIndex]', e)`) so the real error is visible — currently it is swallowed.","Verify the changelog index file is present and valid in the deployed artifact.","On the client, fall back to a cached/empty changelog and show a retry link.","If `ChangelogService` fetches remotely, check the source URL and timeout."],"exampleFix":"// before\n} catch (e) {\n  throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to fetch changelog index' });\n}\n\n// after — log the cause for ops\n} catch (e) {\n  console.error('[changelog:getIndex]', e);\n  throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', cause: e, message: 'Failed to fetch changelog index' });\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":"const isInternalServerError = (e: unknown): boolean =>\n  typeof e === 'object' && e !== null && (e as any).data?.code === 'INTERNAL_SERVER_ERROR';","tryCatchPattern":"try {\n  const index = await trpc.changelog.getIndex.query();\n} catch (e) {\n  if (isInternalServerError(e)) { showCachedOrEmptyChangelog(); return; }\n  throw e;\n}","preventionTips":["Patch the handler to log `e` and attach `cause` — currently the root cause is swallowed.","Ensure the changelog index file is bundled and valid in every deploy.","Cache the index client-side for graceful degradation."],"tags":["trpc","internal-server-error","changelog","content","observability"],"backgroundTag":null,"analyzedSha":"10f24d7ade75139093a9373b364f6bc91f3cd7db","analyzedAt":"2026-08-12T11:43:19.543Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}