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
- Set CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES to a JSON object keyed by project name, e.g. {"myproject":{"chatId":"123","token":"..."}}.
- Validate locally with JSON.parse and check typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) before saving the setting.
- 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
- Validate the JSON shape in the settings UI before saving.
- Test settings values by parsing them in a scratch script.
- Never wrap the object in extra quotes (no double-encoded JSON).
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
- canonical content
- canonical content
- cloud sync canonical payload
- Corrupt JSON file, refusing to overwrite
- Invalid , using default
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)