lobehub/lobehub · error · TRPCError

INTERNAL_SERVER_ERROR

INTERNAL_SERVER_ERROR

Error message

Failed to fetch changelog index

What it means

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.

Source

Thrown at apps/server/src/routers/lambda/changelog.ts:20

import { z } from 'zod';

import { publicProcedure, router } from '@/libs/trpc/lambda';
import { ChangelogService } from '@/server/services/changelog';

const changelogProcedure = publicProcedure.use(async ({ next }) => {
  return next({
    ctx: {
      changelogService: new ChangelogService(),
    },
  });
});

export const changelogRouter = router({
  getIndex: changelogProcedure.query(async ({ ctx }) => {
    try {
      return await ctx.changelogService.getChangelogIndex();
    } catch (e) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to fetch changelog index',
      });
    }
  }),

  getPostById: changelogProcedure
    .input(
      z.object({
        id: z.string(),
        locale: z.string().optional(),
      }),
    )
    .query(async ({ input, ctx }) => {
      try {
        return await ctx.changelogService.getPostById(input.id, { locale: input.locale as any });
      } catch (e) {
        throw new TRPCError({

View on GitHub (pinned to 10f24d7ade)

Solutions

  1. Patch the handler to log the cause (`console.error('[changelog:getIndex]', e)`) so the real error is visible — currently it is swallowed.
  2. Verify the changelog index file is present and valid in the deployed artifact.
  3. On the client, fall back to a cached/empty changelog and show a retry link.
  4. If `ChangelogService` fetches remotely, check the source URL and timeout.

Example fix

// before
} catch (e) {
  throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to fetch changelog index' });
}

// after — log the cause for ops
} catch (e) {
  console.error('[changelog:getIndex]', e);
  throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', cause: e, message: 'Failed to fetch changelog index' });
}
Defensive patterns

Strategy: fallback

Type guard

const isInternalServerError = (e: unknown): boolean =>
  typeof e === 'object' && e !== null && (e as any).data?.code === 'INTERNAL_SERVER_ERROR';

Try / catch

try {
  const index = await trpc.changelog.getIndex.query();
} catch (e) {
  if (isInternalServerError(e)) { showCachedOrEmptyChangelog(); return; }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: First deploy where the changelog content wasn't bundled; a content PR introduced malformed frontmatter; read-only filesystem mount failure.

Related errors


AI-assisted analysis of lobehub/lobehub@10f24d7ade (2026-08-12). Data as JSON: /api/errors/85e7aeffa39850fb. Report an issue: GitHub.