thedotmack/claude-mem · error

CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES must be a JSON object

Error message

CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES must be a JSON object

What it means

loadTelegramWrapupConfig parses the CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES setting as JSON and validates it with isRouteMap before using it as a project-to-route mapping. It throws this error when the parsed value is valid JSON but not a plain object (e.g. an array, string, number, or null), since routes must be keyed by project name.

Solutions

  1. Set CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES to a JSON object keyed by project name, e.g. {"myproject":{"chatId":"123","token":"..."}}.
  2. Validate locally with JSON.parse and check typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) before saving the setting.
  3. If the value is empty or unusable, unset it entirely — the code defaults to '{}' when the setting is empty.

Example fix

// before
CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES=[{"project":"app"}]
// after
CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES={"app":{"chatId":"123456","token":"bot-token"}}
Defensive patterns

Strategy: validation

Validate before calling

const parsed = JSON.parse(raw || '{}');
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
  throw new Error('CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES must be a JSON object');
}

Type guard

function isRouteMap(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try {
  config = loadTelegramWrapupConfig(settings);
} catch (err) {
  logger.error('Invalid TELEGRAM_WRAPUP_ROUTES, disabling wrapup notifier', err);
  config = { routes: {} };
}

Prevention

When it happens

Trigger: Settings.CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES is set to JSON that parses to a non-object, such as '[{"project":"x"}]' (array), '"abc"' (string), '42', or 'null'. Called from the config loader during worker startup.

Common situations: User pastes a JSON array instead of an object into settings; a quoted string of JSON ('"{}"') double-encodes the value; a migration or UI writes the wrong JSON shape.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/c0236af0d747dfa3. Report an issue: GitHub.

Appendix: source

Thrown at src/services/integrations/TelegramWrapupNotifier.ts:73

    return null;
  }
  if (value.bot_token !== undefined && typeof value.bot_token !== 'string') {
    return null;
  }
  if (value.key !== undefined && typeof value.key !== 'string') {
    return null;
  }
  return {
    chat_id: value.chat_id,
    ...(typeof value.bot_token === 'string' ? { bot_token: value.bot_token } : {}),
    ...(typeof value.key === 'string' ? { key: value.key } : {}),
  };
}

export function loadTelegramWrapupConfig(settings: SettingsDefaults): TelegramWrapupConfig {
  const parsedRoutes: unknown = JSON.parse(settings.CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES || '{}');
  if (!isRouteMap(parsedRoutes)) {
    throw new Error('CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES must be a JSON object');
  }

  const routes: Record<string, TelegramWrapupRoute> = {};
  for (const [project, routeValue] of Object.entries(parsedRoutes)) {
    const route = toRoute(routeValue);
    if (route) {
      routes[project] = route;
    }
  }

  return {
    enabled: settings.CLAUDE_MEM_TELEGRAM_ENABLED === 'true',
    wrapupsEnabled: settings.CLAUDE_MEM_TELEGRAM_WRAPUPS_ENABLED === 'true',
    botToken: settings.CLAUDE_MEM_TELEGRAM_BOT_TOKEN,
    routes,
  };
}

View on GitHub (pinned to d8bc9755e7)