ssssssss-team/spider-flow · error · Error
Overlays may not be stateful.
Error message
Overlays may not be stateful.
What it means
Overlays re-tokenize the visible document on every render and must be stateless — a mode with startState() needs persistent state that overlays don't support. addOverlay throws if the resolved mode defines startState.
Solutions
- Write a stateless overlay: a {token: function(stream){...}} spec without startState/copyState
- If you need a stateful mode's highlighting, set it as the editor's main mode instead of an overlay
- Strip startState from your overlay spec (track any needed flags with closures over plain variables only if they reset per token — state cannot persist)
Example fix
// before
cm.addOverlay({name: "javascript"}); // stateful
// after
cm.addOverlay({
token: function(stream) {
if (stream.match("TODO")) { return "keyword"; }
while (stream.next() != null) {}
return null;
}
}); Defensive patterns
Strategy: validation
Validate before calling
function canAddOverlay(cm, spec) {
var mode = spec.token ? spec : CodeMirror.getMode(cm.options, spec);
return !(mode && typeof mode.startState === "function");
}
if (!canAddOverlay(cm, spec)) throw new Error("Overlay spec must be stateless"); Type guard
function isStatelessMode(mode) {
return mode && typeof mode.token === "function" && typeof mode.startState !== "function";
} Try / catch
try {
cm.addOverlay(spec);
} catch (e) {
if (/stateful/.test(e.message)) {
cm.setOption("mode", spec); // use as main mode instead
} else { throw e; }
} Prevention
- Overlays only accept {token: fn} specs or modes without startState — don't pass full language mode names
- Copy overlay templates carefully and delete startState/copyState/indent stubs
- Need rich stateful highlighting? Set the mode via the 'mode' option, not addOverlay
When it happens
Trigger: cm.addOverlay({token: fn, startState: fn}) or addOverlay('someMode') / addOverlay({name: 'javascript'}) where the underlying mode is stateful (most C-like modes are).
Common situations: Trying to overlay a full language mode (e.g. 'xml', 'javascript') instead of a small stateless highlighter, or a custom overlay spec that copied a template including startState.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Mode " + mode.name + " failed to advance stream.
- There is no line " + (n + doc.first) + " in the document.
- This document is already in use.
- Inserting collapsed marker partially overlapping an…
- Unrecognized modifier name: " + mod
AI-assisted analysis of ssssssss-team/spider-flow@c799cca99c (2026-09-08).
Data as JSON: /api/errors/8ee3d48804277ba6.
Report an issue: GitHub.
Appendix: source
Thrown at spider-flow-web/src/main/resources/static/js/codemirror/codemirror.js:8250
getOption: function(option) {return this.options[option]},
getDoc: function() {return this.doc},
addKeyMap: function(map$$1, bottom) {
this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map$$1));
},
removeKeyMap: function(map$$1) {
var maps = this.state.keyMaps;
for (var i = 0; i < maps.length; ++i)
{ if (maps[i] == map$$1 || maps[i].name == map$$1) {
maps.splice(i, 1);
return true
} }
},
addOverlay: methodOp(function(spec, options) {
var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
if (mode.startState) { throw new Error("Overlays may not be stateful.") }
insertSorted(this.state.overlays,
{mode: mode, modeSpec: spec, opaque: options && options.opaque,
priority: (options && options.priority) || 0},
function (overlay) { return overlay.priority; });
this.state.modeGen++;
regChange(this);
}),
removeOverlay: methodOp(function(spec) {
var this$1 = this;
var overlays = this.state.overlays;
for (var i = 0; i < overlays.length; ++i) {
var cur = overlays[i].modeSpec;
if (cur == spec || typeof spec == "string" && cur.name == spec) {
overlays.splice(i, 1);
this$1.state.modeGen++;
regChange(this$1);
returnView on GitHub (pinned to c799cca99c)