{"record":{"id":"3a4f75c99e54e9ab","repo":"eyaltoledano/claude-task-master","slug":"expectedtotal-cannot-be-negative","errorCode":null,"errorMessage":"expectedTotal cannot be negative","messagePattern":"expectedTotal cannot be negative","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/utils/stream-parser.js","lineNumber":65,"sourceCode":"\t\tthis.itemValidator =\n\t\t\tconfig.itemValidator || StreamParserConfig.defaultItemValidator;\n\t\tthis.maxBufferSize = config.maxBufferSize || DEFAULT_MAX_BUFFER_SIZE;\n\n\t\tthis.validate();\n\t}\n\n\tvalidate() {\n\t\tif (!this.jsonPaths || !Array.isArray(this.jsonPaths)) {\n\t\t\tthrow new Error('jsonPaths is required and must be an array');\n\t\t}\n\t\tif (this.jsonPaths.length === 0) {\n\t\t\tthrow new Error('jsonPaths array cannot be empty');\n\t\t}\n\t\tif (this.maxBufferSize <= 0) {\n\t\t\tthrow new Error('maxBufferSize must be positive');\n\t\t}\n\t\tif (this.expectedTotal < 0) {\n\t\t\tthrow new Error('expectedTotal cannot be negative');\n\t\t}\n\t\tif (this.estimateTokens && typeof this.estimateTokens !== 'function') {\n\t\t\tthrow new Error('estimateTokens must be a function');\n\t\t}\n\t\tif (this.onProgress && typeof this.onProgress !== 'function') {\n\t\t\tthrow new Error('onProgress must be a function');\n\t\t}\n\t\tif (this.onError && typeof this.onError !== 'function') {\n\t\t\tthrow new Error('onError must be a function');\n\t\t}\n\t\tif (\n\t\t\tthis.fallbackItemExtractor &&\n\t\t\ttypeof this.fallbackItemExtractor !== 'function'\n\t\t) {\n\t\t\tthrow new Error('fallbackItemExtractor must be a function');\n\t\t}\n\t\tif (this.itemValidator && typeof this.itemValidator !== 'function') {\n\t\t\tthrow new Error('itemValidator must be a function');","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/src/utils/stream-parser.js#L47-L83","documentation":"StreamParser validates that expectedTotal, the expected number of items used for progress estimation, is not negative. A negative value would corrupt percentage calculations and progress reporting. The check runs synchronously in the constructor's validate() step.","triggerScenarios":"new StreamParser({ jsonPaths: [...], expectedTotal: -1 }) or computing expectedTotal from a length/size expression that underflows (e.g. someArray.length - extra where extra > length).","commonSituations":"Doing arithmetic like total - alreadyProcessed without clamping to 0; initializing a counter with -1 as a 'sentinel' and passing it straight into the constructor.","solutions":["Pass 0 or a positive integer for expectedTotal.","Clamp computed values: expectedTotal: Math.max(0, computedTotal).","Omit expectedTotal if the total is unknown."],"exampleFix":"// before\nnew StreamParser({ jsonPaths: ['$.items'], expectedTotal: items.length - processed })\n// after\nnew StreamParser({ jsonPaths: ['$.items'], expectedTotal: Math.max(0, items.length - processed) })","handlingStrategy":"validation","validationCode":"function assertExpectedTotal(t) {\n  if (t !== undefined && (!(Number.isInteger(t)) || t < 0)) {\n    throw new RangeError(`expectedTotal must be a non-negative integer, got ${t}`);\n  }\n  return t;\n}\nnew StreamParser({ ...options, expectedTotal: assertExpectedTotal(options.expectedTotal) });","typeGuard":"function isNonNegativeInt(v) {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 0;\n}","tryCatchPattern":"try {\n  const parser = new StreamParser(options);\n} catch (err) {\n  if (err.message === 'expectedTotal cannot be negative') {\n    options.expectedTotal = Math.max(0, options.expectedTotal);\n    return new StreamParser(options);\n  }\n  throw err;\n}","preventionTips":["Clamp computed totals with Math.max(0, value).","Don't use negative numbers as sentinels for 'unknown' totals; use undefined instead.","Test progress math with edge inputs (empty arrays, already-processed > total)."],"tags":["configuration","validation","progress"],"backgroundTag":"invalid-configuration-value","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}