{"record":{"id":"c1ae6816cacf7f6b","repo":"babalae/better-genshin-impact","slug":"error-c1ae68","errorCode":null,"errorMessage":"未处于录制中状态，无法停止","messagePattern":"未处于录制中状态，无法停止","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"warning","filePath":"BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs","lineNumber":118,"sourceCode":"            if (taskTriggerStopped)\n            {\n                TaskTriggerDispatcher.Instance().StartTimer();\n            }\n\n            Status = KeyMouseRecorderStatus.Stop;\n            _logger.LogError(ex, \"启动键鼠录制失败，相对鼠标捕获方式：{InputType}\", inputType);\n            await ThemedMessageBox.ErrorAsync(\n                $\"启动键鼠录制失败：{ex.Message}\",\n                \"键鼠录制启动失败\");\n            return false;\n        }\n    }\n\n    public string StopRecord()\n    {\n        if (Status != KeyMouseRecorderStatus.Recording)\n        {\n            throw new InvalidOperationException(\"未处于录制中状态，无法停止\");\n        }\n\n        _timer.Stop();\n\n        var recorder = _recorder;\n        _recorder = null;\n        var relativeMouseSubscription = _relativeMouseSubscription;\n        _relativeMouseSubscription = null;\n\n        try\n        {\n            relativeMouseSubscription?.Dispose();\n            return recorder?.ToJsonMacro() ?? string.Empty;\n        }\n        finally\n        {\n            _logger.LogInformation(\"录制：{Text}\", \"结束录制\");\n            TaskTriggerDispatcher.Instance().StartTimer();","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs#L100-L136","documentation":"StopRecord requires the recorder to be in the Recording state. If Status is anything else (Start in progress, or Stop), it throws InvalidOperationException because there is no active session to finalize and serializing now would lose data or produce garbage.","triggerScenarios":"The stop hotkey fires when no recording is active; StopRecord is called twice in quick succession; the stop handler runs after StartRecord failed and reset status to Stop.","commonSituations":"Hotkey double-fire; stop UI button enabled while not recording; race between StartRecord's countdown and a stop press; caller ignored that StartRecord returned false.","solutions":["Check Status == KeyMouseRecorderStatus.Recording before calling StopRecord.","Guard the stop hotkey handler to ignore presses when not recording.","Disable the stop button/UI when Status is not Recording.","Ensure callers react to a failed StartRecord (returns false) instead of proceeding to StopRecord."],"exampleFix":"// before\npublic string StopRecord()\n{\n    if (Status != KeyMouseRecorderStatus.Recording)\n        throw new InvalidOperationException(\"未处于录制中状态，无法停止\");\n    // ...\n}\n\n// after: no-op when idle\npublic string StopRecord()\n{\n    if (Status != KeyMouseRecorderStatus.Recording)\n    {\n        _logger.LogWarning(\"StopRecord ignored: current status is {Status}\", Status);\n        return string.Empty;\n    }\n    // ...\n}","handlingStrategy":"validation","validationCode":"if (GlobalKeyMouseRecord.Instance.Status != KeyMouseRecorderStatus.Recording)\n{\n    // not recording; ignore or log instead of stopping\n    return string.Empty;\n}\nreturn GlobalKeyMouseRecord.Instance.StopRecord();","typeGuard":"static bool IsRecording => GlobalKeyMouseRecord.Instance.Status == KeyMouseRecorderStatus.Recording;","tryCatchPattern":"try { return GlobalKeyMouseRecord.Instance.StopRecord(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"未处于录制中状态\"))\n{ _logger.LogWarning(ex, \"StopRecord called while not recording.\"); return string.Empty; }","preventionTips":["Gate the stop hotkey and stop UI button on Status == Recording.","Treat a failed StartRecord (returns false) as 'not recording' before allowing stop.","Make StopRecord idempotent by returning early when idle instead of throwing."],"tags":["recording","state-machine","validation","mouse"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}