{"record":{"id":"73c0afdeae4d5933","repo":"ssssssss-team/spider-flow","slug":"inserting-collapsed-marker-partially-overlapping-a","errorCode":null,"errorMessage":"Inserting collapsed marker partially overlapping an existing one","messagePattern":"Inserting collapsed marker partially overlapping an existing one","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"spider-flow-web/src/main/resources/static/js/codemirror/codemirror.js","lineNumber":5961,"sourceCode":"    // Ensure we are in an operation.\n    if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }\n\n    var marker = new TextMarker(doc, type), diff = cmp(from, to);\n    if (options) { copyObj(options, marker, false); }\n    // Don't connect empty markers unless clearWhenEmpty is false\n    if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)\n      { return marker }\n    if (marker.replacedWith) {\n      // Showing up as a widget implies collapsed (widget replaces text)\n      marker.collapsed = true;\n      marker.widgetNode = eltP(\"span\", [marker.replacedWith], \"CodeMirror-widget\");\n      if (!options.handleMouseEvents) { marker.widgetNode.setAttribute(\"cm-ignore-events\", \"true\"); }\n      if (options.insertLeft) { marker.widgetNode.insertLeft = true; }\n    }\n    if (marker.collapsed) {\n      if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||\n          from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))\n        { throw new Error(\"Inserting collapsed marker partially overlapping an existing one\") }\n      seeCollapsedSpans();\n    }\n\n    if (marker.addToHistory)\n      { addChangeToHistory(doc, {from: from, to: to, origin: \"markText\"}, doc.sel, NaN); }\n\n    var curLine = from.line, cm = doc.cm, updateMaxLine;\n    doc.iter(curLine, to.line + 1, function (line) {\n      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)\n        { updateMaxLine = true; }\n      if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }\n      addMarkedSpan(line, new MarkedSpan(marker,\n                                         curLine == from.line ? from.ch : null,\n                                         curLine == to.line ? to.ch : null));\n      ++curLine;\n    });\n    // lineIsHidden depends on the presence of the spans, so needs a second pass\n    if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {","sourceCodeStart":5943,"sourceCodeEnd":5979,"githubUrl":"https://github.com/ssssssss-team/spider-flow/blob/c799cca99c7d064673dc79e6ef06a08bbc0e292d/spider-flow-web/src/main/resources/static/js/codemirror/codemirror.js#L5943-L5979","documentation":"markText()/setBookmark() with {collapsed: true} refuse to create a collapsed marker that partially overlaps another collapsed marker on the same line. Partial collapse overlap is unrepresentable in the rendering model, so CodeMirror throws.","triggerScenarios":"Calling cm.markText(from, to, {collapsed: true}) where the range partially intersects an existing collapsed range (shared endpoint overlap covering only part of the existing range) on from.line or to.line.","commonSituations":"Code-folding plugins folding overlapping regions, users folding already-folded sub-regions, or programmatic annotations applying collapsed markers over widget bookmarks.","solutions":["Check for existing collapsed marks first (cm.findMarksAt / cm.getAllMarks with mark.collapsed) and skip or expand the new range to fully contain/avoid them","Unfold (mark.clear()) the conflicting collapsed range before inserting the new one","Use non-collapsed marks (className only) when overlapping highlighting is needed"],"exampleFix":"// before\ncm.markText(from, to, {collapsed: true});\n// after\nvar conflicting = cm.findMarksAt(from).concat(cm.findMarksAt(to))\n  .some(function(m){ return m.collapsed; });\nif (!conflicting) { cm.markText(from, to, {collapsed: true}); }","handlingStrategy":"validation","validationCode":"function hasCollapsedConflict(cm, from, to) {\n  var lines = [from.line];\n  if (to.line !== from.line) lines.push(to.line);\n  return lines.some(function(l) {\n    return cm.findMarksAt({line: l, ch: 0}).some(function(m) { return m.collapsed; });\n  });\n}\nif (hasCollapsedConflict(cm, from, to)) { /* clear or skip */ }","typeGuard":null,"tryCatchPattern":"try {\n  var mark = cm.markText(from, to, {collapsed: true});\n} catch (e) {\n  if (/partially overlapping/.test(e.message)) {\n    var mark = cm.markText(from, to, {className: \"my-highlight\"}); // non-collapsed fallback\n  } else { throw e; }\n}","preventionTips":["Track your own list of active collapsed ranges and check overlap before creating new ones","Clear existing folded marks before re-folding a region","Only use collapsed:true for non-overlapping structure (folding); use className for overlapping highlights"],"tags":["codemirror","marker","folding"],"backgroundTag":"invalid-state-transition","analyzedSha":"c799cca99c7d064673dc79e6ef06a08bbc0e292d","analyzedAt":"2026-09-08T13:47:08.225Z","contentChangedAt":"2026-09-08T13:47:08.225Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}