mastra-ai/mastra · error
[QueueHealthStorage] thresholdsSeconds must be a non-empty a
Error message
[QueueHealthStorage] thresholdsSeconds must be a non-empty array of finite numbers.
What it means
assertValidThresholds validates QueueHealthConfig.thresholdsSeconds at the write boundary. It throws this error when the value is not an array, is empty, or contains any element that is not a finite number (NaN/Infinity included). Descending or duplicate thresholds have their own message.
Source
Thrown at mastracode/factory/src/storage/domains/queue-health/base.ts:35
export interface QueueHealthConfig {
/** Ordered-ascending age boundaries in seconds, e.g. `[14400, 86400, 259200]`. */
thresholdsSeconds: number[];
}
/** Default: green <4h, amber <24h, orange <72h, red 72h+. */
export const DEFAULT_QUEUE_HEALTH_CONFIG: QueueHealthConfig = {
thresholdsSeconds: [14400, 86400, 259200],
};
/**
* Throw unless `thresholdsSeconds` is a non-empty ascending number list. A
* descending config would silently invert bucket semantics, so validate at the
* write boundary rather than trusting callers.
*/
export function assertValidThresholds(config: QueueHealthConfig): void {
const t = config.thresholdsSeconds;
if (!Array.isArray(t) || t.length === 0 || t.some(v => typeof v !== 'number' || !Number.isFinite(v))) {
throw new Error('[QueueHealthStorage] thresholdsSeconds must be a non-empty array of finite numbers.');
}
for (let i = 1; i < t.length; i++) {
if (t[i]! <= t[i - 1]!) {
throw new Error('[QueueHealthStorage] thresholdsSeconds must be strictly ascending.');
}
}
}
/** Validate untrusted JSON into a `QueueHealthConfig`, or `null` when invalid. */
export function parseQueueHealthConfig(body: unknown): QueueHealthConfig | null {
if (typeof body !== 'object' || body === null) return null;
const config = body as { thresholdsSeconds?: unknown };
if (!Array.isArray(config.thresholdsSeconds)) return null;
try {
assertValidThresholds(config as QueueHealthConfig);
} catch {
return null;
}View on GitHub (pinned to 75dd419e61)
Solutions
- Provide a non-empty array of finite numbers for thresholdsSeconds
- Replace Infinity/NaN sentinels with concrete numeric bounds
- Guard the config file parsing so missing/empty thresholds are rejected before save
- Use parseQueueHealthConfig to validate untrusted JSON before persisting
Example fix
// before
await storage.saveConfig({ thresholdsSeconds: [60, Infinity] });
// after
await storage.saveConfig({ thresholdsSeconds: [60, 300, 900] }); Defensive patterns
Strategy: validation
Validate before calling
function isValidThresholds(t: unknown): t is number[] {
return Array.isArray(t) && t.length > 0 && t.every(v => typeof v === 'number' && Number.isFinite(v));
}
if (!isValidThresholds(config.thresholdsSeconds)) throw new Error('thresholdsSeconds must be a non-empty finite number array'); Type guard
function isQueueHealthConfig(body: unknown): body is QueueHealthConfig {
const t = (body as QueueHealthConfig | undefined)?.thresholdsSeconds;
return isValidThresholds(t);
} Try / catch
try {
await storage.saveConfig(config);
} catch (e) {
if (e instanceof Error && e.message.includes('non-empty array of finite numbers')) {
throw new BadRequest('thresholdsSeconds is required as a non-empty list of finite numbers');
}
throw e;
} Prevention
- Run untrusted JSON through parseQueueHealthConfig before saving
- Reject NaN/Infinity sentinels in config validation
- Give thresholds sane defaults instead of empty arrays
- Type the config schema so empty arrays fail at build/parse time
When it happens
Trigger: Calling saveConfig (or parseQueueHealthConfig) with thresholdsSeconds = [], undefined, a non-array, or an array containing NaN/Infinity/strings/nulls.
Common situations: Config loaded from a JSON file where the key was missing or the array was emptied by a filter; UI submitting an un-filled thresholds list; Infinity used as a sentinel upper bound.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- [QueueHealthStorage] thresholdsSeconds must be strictly asce
- Cookie password must be at least 32 characters. Set WORKOS_C
- Factory rule version is required.
- ${label} must be an object.
- Factory rules must be an object.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/15bc103bd853ce90.
Report an issue: GitHub.