{"record":{"id":"7351febf7017d295","repo":"CoplayDev/unity-mcp","slug":"failed-to-write-config-file-path-ex-message","errorCode":null,"errorMessage":"Failed to write config file '{path}': {ex.Message}","messagePattern":"Failed to write config file '(.+?)': (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"MCPForUnity/Editor/Helpers/McpConfigurationHelper.cs","lineNumber":274,"sourceCode":"                        }\n                        catch { }\n                        File.Move(path, backup);\n                    }\n                    File.Move(tmp, path);\n                    writeDone = true;\n                }\n            }\n            catch (Exception ex)\n            {\n                try\n                {\n                    if (!writeDone && File.Exists(backup))\n                    {\n                        try { File.Copy(backup, path, true); } catch { }\n                    }\n                }\n                catch { }\n                throw new Exception($\"Failed to write config file '{path}': {ex.Message}\", ex);\n            }\n            finally\n            {\n                try { if (File.Exists(tmp)) File.Delete(tmp); } catch { }\n                try { if (writeDone && File.Exists(backup)) File.Delete(backup); } catch { }\n            }\n        }\n    }\n}\n","sourceCodeStart":256,"sourceCodeEnd":284,"githubUrl":"https://github.com/CoplayDev/unity-mcp/blob/c21bf496bca87d54e75bad048563c3adb1782081/MCPForUnity/Editor/Helpers/McpConfigurationHelper.cs#L256-L284","documentation":"McpConfigurationHelper writes the config atomically: it backs up the original, writes a temp file, then replaces the target. If any step throws, the catch block restores the backup (only if the final write did not complete) and re-throws a generic Exception whose message embeds the original error and whose InnerException is the real cause. The 'finally' cleans up temp/backup files defensively.","triggerScenarios":"The config file is locked by another process; the disk is full; the path is read-only or permission-denied; the path exceeds OS length limits; antivirus quarantines the temp file mid-write.","commonSituations":"Config file left open in a text editor; another Unity/editor instance holding a write lock; a read-only project checkout; concurrent writes from two processes to the same config; transient AV interference.","solutions":["Close any editor or process holding the config file open, then retry.","Ensure write permission on the config path and that the disk has free space.","Inspect the InnerException for the true underlying error rather than the wrapper message.","Avoid running two instances that write the same config concurrently."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-check the config path is writable before attempting the atomic write.\nstring dir = Path.GetDirectoryName(path);\nif (!Directory.Exists(dir)) Directory.CreateDirectory(dir);\nstring probe = Path.Combine(dir, $\".writeprobe_{Guid():N}\");\nFile.WriteAllText(probe, \"\"); File.Delete(probe);","typeGuard":null,"tryCatchPattern":"for (int attempt = 0; attempt < 3; attempt++)\n{\n    try { McpConfigurationHelper.WriteConfig(path, json); break; }\n    catch (Exception ex) when (IsTransientFileError(ex))\n    {\n        if (attempt == 2) throw;\n        await Task.Delay(250 * (attempt + 1));\n    }\n}\n// Inspect ex.InnerException for the real cause when rethrown.","preventionTips":["Do not keep the config file open in another editor while the tool writes it.","Avoid two processes writing the same config concurrently.","Check InnerException for the underlying IO error when this wrapper fires."],"tags":["config","filesystem","io","atomic-write"],"backgroundTag":null,"analyzedSha":"c21bf496bca87d54e75bad048563c3adb1782081","analyzedAt":"2026-08-13T17:36:56.095Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}