thedotmack/claude-mem · error

internal_error

internal_error

Error message

internal_error

What it means

Catch-all 500 from the compat summarize adapter: any exception thrown by summarizeSession (database failures, session lookup errors other than not-found, endSession faults) is logged as 'compat summarize adapter failed' with the contentSessionId, then surfaced as { status: 'error', reason: 'internal_error' }. The response deliberately hides the cause; the server log holds it.

Source

Thrown at src/server/compat/SessionsSummarizeAdapter.ts:85

        return;
      }

      // Subagent contexts in legacy code emit summarize calls but the worker
      // skipped them. We preserve the legacy semantics so existing clients
      // see the same response shape.
      if (parsed.data.agentId) {
        res.json({ status: 'skipped', reason: 'subagent_context' });
        return;
      }

      try {
        await this.summarizeSession(req, res, parsed.data, teamId, projectId);
      } catch (error) {
        logger.error('SYSTEM', 'compat summarize adapter failed', {
          error: error instanceof Error ? error.message : String(error),
          contentSessionId: parsed.data.contentSessionId,
        });
        res.status(500).json({ status: 'error', reason: 'internal_error' });
      }
    }));
  }

  private async summarizeSession(
    req: Request,
    res: Response,
    data: z.infer<typeof summarizeSchema>,
    teamId: string,
    projectId: string,
  ): Promise<void> {
    const platformSource = normalizePlatformSource(
      typeof data.platformSource === 'string'
        ? data.platformSource
        : DEFAULT_PLATFORM_SOURCE,
    );
    const session = await resolveServerSession({
      pool: this.options.pool,

View on GitHub (pinned to e2d1df569a)

Solutions

  1. Check server logs for 'compat summarize adapter failed' — the error message and contentSessionId identify the real cause.
  2. Verify database connectivity and pool health; most instances are transient storage faults.
  3. Confirm the session identified by contentSessionId exists and belongs to the key's team/project.
  4. If it recurs on one session, inspect that session's rows for constraint or state corruption; retry once after fixing.
Defensive patterns

Strategy: try-catch

Type guard

interface Compat500 { status: string; reason: string }
function isInternalError(body: unknown): body is Compat500 {
  return typeof body === 'object' && body !== null &&
    (body as Compat500).status === 'error' && (body as Compat500).reason === 'internal_error';
}

Try / catch

try {
  const res = await fetch(`${base}/api/sessions/summarize`, opts);
  if (res.status === 500) {
    const body = await res.json().catch(() => null);
    if (isInternalError(body)) {
      logger.warn('summarize internal_error', { contentSessionId });
      await sleep(2000);
      return retryOnce(); // transient storage faults are common
    }
  }
  return res;
} catch (e) {
  throw new SummarizeTransportError(String(e));
}

Prevention

When it happens

Trigger: Postgres/SQLite connectivity drop mid-request during endSession; the session row exists at lookup but disappears before the end/outbox transaction; an enqueue failure inside endSession; any unexpected throw in normalizePlatformSource or downstream persistence.

Common situations: DB restart or failover while legacy Claude Code clients flush summarize calls; migrations that rename columns the adapter touches; connection pool exhaustion under load so endSession throws instead of timing out cleanly.

Related errors


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/662294cf164f2601. Report an issue: GitHub.