{"record":{"id":"c614dd3b94df9dac","repo":"microsoft/TypeScript","slug":"length-0","errorCode":null,"errorMessage":"length < 0","messagePattern":"length < 0","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/compiler/utilitiesPublic.ts","lineNumber":451,"sourceCode":"        while (j < spans.length && textSpanIntersectsWithTextSpan(span, spans[j])) {\r\n            const start = Math.min(span.start, spans[j].start);\r\n            const end = Math.max(textSpanEnd(span), textSpanEnd(spans[j]));\r\n            span = createTextSpanFromBounds(start, end);\r\n            j++;\r\n        }\r\n        i = j;\r\n        result.push(span);\r\n    }\r\n\r\n    return result;\r\n}\r\n\r\nexport function createTextSpan(start: number, length: number): TextSpan {\r\n    if (start < 0) {\r\n        throw new Error(\"start < 0\");\r\n    }\r\n    if (length < 0) {\r\n        throw new Error(\"length < 0\");\r\n    }\r\n\r\n    return { start, length };\r\n}\r\n\r\nexport function createTextSpanFromBounds(start: number, end: number): TextSpan {\r\n    return createTextSpan(start, end - start);\r\n}\r\n\r\nexport function textChangeRangeNewSpan(range: TextChangeRange): TextSpan {\r\n    return createTextSpan(range.span.start, range.newLength);\r\n}\r\n\r\nexport function textChangeRangeIsUnchanged(range: TextChangeRange): boolean {\r\n    return textSpanIsEmpty(range.span) && range.newLength === 0;\r\n}\r\n\r\nexport function createTextChangeRange(span: TextSpan, newLength: number): TextChangeRange {\r","sourceCodeStart":433,"sourceCodeEnd":469,"githubUrl":"https://github.com/microsoft/TypeScript/blob/b465fdbfe175304d9b977da137b2c178ae1091d3/src/compiler/utilitiesPublic.ts#L433-L469","documentation":"Thrown by `ts.createTextSpan(start, length)` when `length` is negative. Since `createTextSpanFromBounds(start, end)` calls `createTextSpan(start, end - start)`, passing bounds where `end < start` also produces this error.","triggerScenarios":"Calling `createTextSpan` with a negative `length`, or `createTextSpanFromBounds` with reversed/out-of-order `start`/`end` (end before start), usually due to inverted node positions or wrong subtraction order.","commonSituations":"Transforms computing `end - start` with swapped operands; editing ranges from incremental edits where the new range is empty or inverted; converting selection anchors that can be backwards.","solutions":["Ensure `length >= 0` (and `end >= start` for the bounds variant) before calling.","Sort the two positions when they can arrive in either order: `const [a, b] = [p, q].sort((x,y)=>x-y);`.","Use `ts.textSpanIsEmpty` / construct `createTextSpan(pos, 0)` for zero-length needs."],"exampleFix":"// before\nconst span = ts.createTextSpanFromBounds(node.end, node.pos); // end<pos -> length<0\n// after\nconst span = ts.createTextSpanFromBounds(node.pos, node.end);    // pos <= end","handlingStrategy":"validation","validationCode":"function safeSpanFromBounds(start: number, end: number): ts.TextSpan {\n  if (end < start) [start, end] = [end, start];\n  return ts.createTextSpanFromBounds(start, end);\n}","typeGuard":"function isValidBounds(start: number, end: number): boolean { return Number.isInteger(start) && Number.isInteger(end) && start >= 0 && end >= start; }","tryCatchPattern":null,"preventionTips":["Always pass `pos` first, `end` second for nodes.","Sort externally-derived anchor pairs before building a span."],"tags":["textspan","compiler-api","internal-invariant","position"],"backgroundTag":null,"analyzedSha":"b465fdbfe175304d9b977da137b2c178ae1091d3","analyzedAt":"2026-08-12T05:38:42.698Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}