{"record":{"id":"e89de0f785b3259f","repo":"affaan-m/ECC","slug":"invalid-limit-value","errorCode":null,"errorMessage":"Invalid limit: ${value}","messagePattern":"Invalid limit: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/state-store/queries.js","lineNumber":18,"sourceCode":"'use strict';\n\nconst { assertValidEntity } = require('./schema');\n\nconst ACTIVE_SESSION_STATES = ['active', 'running', 'idle'];\nconst SUCCESS_OUTCOMES = new Set(['success', 'succeeded', 'passed']);\nconst FAILURE_OUTCOMES = new Set(['failure', 'failed', 'error']);\nconst CLOSED_WORK_ITEM_STATUSES = new Set(['done', 'closed', 'resolved', 'merged', 'cancelled']);\nconst ATTENTION_WORK_ITEM_STATUSES = new Set(['blocked', 'needs-review', 'failed', 'stalled']);\n\nfunction normalizeLimit(value, fallback) {\n  if (value === undefined || value === null) {\n    return fallback;\n  }\n\n  const parsed = Number.parseInt(value, 10);\n  if (!Number.isFinite(parsed) || parsed <= 0) {\n    throw new Error(`Invalid limit: ${value}`);\n  }\n\n  return parsed;\n}\n\nfunction parseJsonColumn(value, fallback) {\n  if (value === null || value === undefined || value === '') {\n    return fallback;\n  }\n\n  return JSON.parse(value);\n}\n\nfunction stringifyJson(value, label) {\n  try {\n    return JSON.stringify(value);\n  } catch (error) {\n    throw new Error(`Failed to serialize ${label}: ${error.message}`);","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/state-store/queries.js#L1-L36","documentation":"normalizeLimit turns an optional limit value into a positive integer, falling back to a default when undefined/null. Any other input that does not parse (via parseInt) into a finite positive integer — 0, negative numbers, NaN, floats with fraction, non-numeric strings — throws. It backs limit, activeLimit, recentSkillRunLimit, pendingLimit, and workItemLimit query options.","triggerScenarios":"Calling a query function with limit: 0, limit: -5, limit: 'ten', limit: 2.5, or limit: NaN; passing a limit string like '10abc' which parseInt yields 10 for but 'abc' yields NaN for and throws.","commonSituations":"User-supplied pagination values passed through from CLI/HTTP without validation; off-by-one code computing limit as count-1 when count is 0; environment/config variables holding placeholder text; JSON configs where the limit was accidentally an object or empty string.","solutions":["Pass a positive integer (or omit the value to use the fallback)","Coerce and validate at the boundary: n = Number.parseInt(raw, 10); if (!Number.isFinite(n) || n <= 0) use default","Fix upstream parsing so numeric query params are converted before reaching the query layer","Remove sentinel values like 0 or -1 meant to mean 'unlimited' — omit the option instead"],"exampleFix":"// before\nqueryActive({ limit: 0 });\n// after\nconst limit = Number(rawLimit);\nqueryActive({ limit: Number.isFinite(limit) && limit > 0 ? limit : undefined });","handlingStrategy":"validation","validationCode":"function toLimit(raw, fallback) {\n  if (raw === undefined || raw === null) return fallback;\n  const n = Number.parseInt(raw, 10);\n  return Number.isFinite(n) && n > 0 ? n : fallback;\n}\nconst limit = toLimit(rawLimit, 50);","typeGuard":"function isValidLimit(v) {\n  const n = Number(v);\n  return Number.isInteger(n) && n > 0;\n}","tryCatchPattern":"try {\n  return queryActive({ limit });\n} catch (err) {\n  if (err.message.startsWith('Invalid limit')) {\n    console.warn(`Bad limit '${limit}' — using default`);\n    return queryActive({});\n  } throw err;\n}","preventionTips":["Sanitize user/HTTP/CLI limit input at the boundary with parseInt and a range check","Use undefined, not 0 or -1, to mean 'use the default'","Validate numeric config keys at startup","Never forward raw string query params into query options"],"tags":["validation","pagination"],"backgroundTag":"invalid-argument-value","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}