From 02050425bba31de1e904719d097c9968d3983030 Mon Sep 17 00:00:00 2001 From: pedrofrxncx Date: Thu, 23 Jul 2026 17:36:42 -0300 Subject: [PATCH] fix(settings): validate CLICKHOUSE_MAX_MEMORY_USAGE instead of silently ignoring invalid values --- apps/mesh/src/settings/resolve-config.test.ts | 25 +++++++++++++++++++ apps/mesh/src/settings/resolve-config.ts | 19 ++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/apps/mesh/src/settings/resolve-config.test.ts b/apps/mesh/src/settings/resolve-config.test.ts index 34399836d2..25ee4674da 100644 --- a/apps/mesh/src/settings/resolve-config.test.ts +++ b/apps/mesh/src/settings/resolve-config.test.ts @@ -132,6 +132,31 @@ describe("resolveConfig port", () => { ); }); +describe("resolveConfig clickhouse max memory usage", () => { + it("defaults to undefined when unset", () => { + const result = resolveConfig(flags, {}); + + expect(result.settings.clickhouseMaxMemoryUsage).toBeUndefined(); + }); + + it("uses CLICKHOUSE_MAX_MEMORY_USAGE when set", () => { + const result = resolveConfig(flags, { + CLICKHOUSE_MAX_MEMORY_USAGE: "1000000000", + }); + + expect(result.settings.clickhouseMaxMemoryUsage).toBe(1000000000); + }); + + it.each(["abc", "0", "-1", "1.5", "Infinity"])( + "throws for invalid value %p", + (value) => { + expect(() => + resolveConfig(flags, { CLICKHOUSE_MAX_MEMORY_USAGE: value }), + ).toThrow("CLICKHOUSE_MAX_MEMORY_USAGE must be a positive integer"); + }, + ); +}); + describe("resolveConfig deployment admin emails", () => { it("defaults to an empty list when unset", () => { const result = resolveConfig(flags, {}); diff --git a/apps/mesh/src/settings/resolve-config.ts b/apps/mesh/src/settings/resolve-config.ts index 0abe293590..1ec87ab1db 100644 --- a/apps/mesh/src/settings/resolve-config.ts +++ b/apps/mesh/src/settings/resolve-config.ts @@ -57,6 +57,19 @@ function toPositiveIntegerOrDefault( return numberValue; } +function toPositiveIntegerOrUndefined( + name: string, + value: string | undefined, +): number | undefined { + if (value === undefined || value === "") return undefined; + + const numberValue = Number(value); + if (!Number.isSafeInteger(numberValue) || numberValue <= 0) { + throw new Error(`${name} must be a positive integer`); + } + return numberValue; +} + /** Tri-state flag: unset/empty → `fallback`, otherwise parse as boolean. */ function toBoolWithDefault( value: string | undefined, @@ -160,8 +173,10 @@ export function resolveConfig( // Observability clickhouseUrl: envVars.CLICKHOUSE_URL, - clickhouseMaxMemoryUsage: - Number(envVars.CLICKHOUSE_MAX_MEMORY_USAGE) || undefined, + clickhouseMaxMemoryUsage: toPositiveIntegerOrUndefined( + "CLICKHOUSE_MAX_MEMORY_USAGE", + envVars.CLICKHOUSE_MAX_MEMORY_USAGE, + ), monitoringOtlpEndpoint: envVars.MONITORING_OTLP_ENDPOINT, otelServiceName: envVars.OTEL_SERVICE_NAME || "studio",