{"record":{"id":"b3e22dd18ddf641a","repo":"Tencent/QMUI_Android","slug":"can-not-perform-action-when-running","errorCode":null,"errorMessage":"can not perform $action when running.","messagePattern":"can not perform \\$action when running\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"type/src/main/java/com/qmuiteam/qmui/type/view/BaseTypeView.kt","lineNumber":93,"sourceCode":"                environment.lineHeight = value\n                requestLayout()\n            }\n        }\n\n    var paragraphSpace: Int\n        get() = environment.paragraphSpace\n        set(value){\n            throwIfRunning(\"setParagraphSpace\")\n            if(environment.paragraphSpace != value){\n                environment.paragraphSpace = value\n                requestLayout()\n            }\n        }\n\n\n    fun throwIfRunning(action: String) {\n        if(environment.isRunning()){\n            throw RuntimeException(\"can not perform $action when running.\")\n        }\n    }\n}","sourceCodeStart":75,"sourceCodeEnd":96,"githubUrl":"https://github.com/Tencent/QMUI_Android/blob/026e7d486677d6593a96689cd590ec3561176717/type/src/main/java/com/qmuiteam/qmui/type/view/BaseTypeView.kt#L75-L96","documentation":"BaseTypeView.throwIfRunning is a guard the type-rendering view calls before mutating operations: while the view's environment is running (a layout/render pass is in progress), structural changes to the type model are illegal and would corrupt the in-flight pass, so a RuntimeException naming the attempted action is thrown.","triggerScenarios":"Invoking a BaseTypeView mutating API (e.g. resetting/replacing type models or adding effects) from inside a callback that fires while the view is running — such as during onLayout/onDraw, inside a listener triggered by the rendering pass, or on a callback invoked by the environment's run loop.","commonSituations":"Updating type content in response to a layout/data-change callback that occurs mid-render; calling invalidate/refill methods from an animation or scroll callback managed by the BaseTypeView itself.","solutions":["Defer the mutation until the running pass completes: post it to the view (view.post { ... }) or a handler.","Move the update out of render-pass callbacks into lifecycle points like onAttachedToWindow, data-set changes, or explicit user actions.","Guard your own call sites with environment.isRunning() checks, or call throwIfRunning yourself before mutating to fail fast with a clear action name."],"exampleFix":"// before\nvoid onDataChanged(List<TypeModel> models) {\n    typeView.resetData(models); // throws if a render pass is running\n}\n\n// after\nvoid onDataChanged(List<TypeModel> models) {\n    typeView.post(() -> typeView.resetData(models));\n}","handlingStrategy":"fallback","validationCode":"if (typeView.getEnvironment().isRunning()) {\n    // defer instead of mutating now\n    typeView.post(() -> typeView.resetData(models));\n    return;\n}\ntypeView.resetData(models);","typeGuard":null,"tryCatchPattern":"try {\n    typeView.resetData(models);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"when running\")) {\n        typeView.post(() -> typeView.resetData(models));\n    } else {\n        throw e;\n    }\n}","preventionTips":["Never mutate BaseTypeView data from layout/draw or environment-run callbacks.","Post mutations to the view's message queue when triggered mid-render.","Call throwIfRunning yourself in wrappers to fail fast with a meaningful action name."],"tags":["android","invalid-state","rendering","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"026e7d486677d6593a96689cd590ec3561176717","analyzedAt":"2026-09-06T13:32:24.816Z","contentChangedAt":"2026-09-06T13:32:24.816Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}