{"record":{"id":"57ea51e7c170e2fc","repo":"tui-cs/Terminal.Gui","slug":"wordwrap-settings-was-changed-after-the-currentc","errorCode":null,"errorMessage":"WordWrap settings was changed after the {_currentCaller} call.","messagePattern":"WordWrap settings was changed after the (.+?) call\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Views/TextInput/TextView/TextView.WordWrap.cs","lineNumber":387,"sourceCode":"                                       out int nStartCol,\n                                       CurrentRow,\n                                       CurrentColumn,\n                                       _selectionStartRow,\n                                       _selectionStartColumn,\n                                       _tabWidth,\n                                       true);\n            CurrentRow = nRow;\n            CurrentColumn = nCol;\n            _selectionStartRow = nStartRow;\n            _selectionStartColumn = nStartCol;\n            _wrapNeeded = true;\n\n            SetNeedsDraw ();\n        }\n\n        if (_currentCaller is { })\n        {\n            throw new InvalidOperationException ($\"WordWrap settings was changed after the {_currentCaller} call.\");\n        }\n    }\n\n    /// <summary>\n    ///     INTERNAL: Wraps or rewraps the text model to fit the current Viewport width.\n    /// </summary>\n    /// <remarks>\n    ///     <para>\n    ///         This method regenerates the wrapped model whenever the viewport width changes or when\n    ///         word wrap is first enabled. It is typically called during layout operations.\n    ///     </para>\n    ///     <para>\n    ///         The wrapping process:\n    ///         <list type=\"bullet\">\n    ///             <item>Takes each line from the original model</item>\n    ///             <item>Breaks it into multiple lines to fit within the viewport width</item>\n    ///             <item>Preserves tab expansion based on <see cref=\"TabWidth\"/></item>\n    ///             <item>Maintains word boundaries (doesn't break words mid-character)</item>","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Views/TextInput/TextView/TextView.WordWrap.cs#L369-L405","documentation":"Thrown by TextView's word-wrap machinery (InvalidOperationException, interpolated message) when _currentCaller is non-null at a point where the wrap routine expected it to be cleared — i.e. word-wrap settings were changed in the middle of an operation tracked by _currentCaller. The wrap pass sets _currentCaller to detect exactly this: if a callee mutates WordWrap while a dependent operation is in flight, the invariants the operation relied on are broken, so it aborts.","triggerScenarios":"Toggling WordWrap (or a setting that forces a rewrap) from within a callback/handler invoked during a TextView operation that set _currentCaller — e.g. changing wrap inside a TextChanged, selection, or layout handler that runs mid-operation.","commonSituations":"A reactive handler that re-enables/disables word wrap in response to content events; programmatic wrap toggles triggered from within command handling; recursive layout driven by a wrap change.","solutions":["Do not mutate WordWrap from within TextView event handlers or commands; defer the change to after the operation completes (e.g. via Application.Invoke/Post).","Gate wrap toggles on user input only, outside the model's own change notifications.","If a programmatic wrap change is required mid-session, queue it and apply it once _currentCaller has cleared."],"exampleFix":"// before\ntextView.TextChanged += (_, _) => { textView.WordWrap = !textView.WordWrap; }; // throws 177\n\n// after\nbool pending = false;\ntextView.TextChanged += (_, _) => pending = true;\n// apply later, outside the operation:\napp.Invoke(() => { if (pending) { textView.WordWrap = !textView.WordWrap; pending = false; } });","handlingStrategy":"validation","validationCode":"// Do not change WordWrap inside TextView handlers; defer\ntextView.TextChanged += (_, _) => { _pendingWrapToggle = true; };\napp.Invoke(() => { if (_pendingWrapToggle) { textView.WordWrap = !textView.WordWrap; _pendingWrapToggle = false; } });","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never mutate WordWrap from within TextView event handlers or commands.","Defer wrap changes to after the current operation completes.","Gate programmatic wrap toggles on user input, not on internal change notifications."],"tags":["textview","wordwrap","state","reentrancy"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}