{"record":{"id":"f0368725d55da36d","repo":"flipped-aurora/gin-vue-admin","slug":"w-f03687","errorCode":null,"errorMessage":"回滚自动代码文件失败: %w","messagePattern":"回滚自动代码文件失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/auto_code_task.go","lineNumber":256,"sourceCode":"\t\tif err = replaceAutoCodeFileAtomically(file.TargetPath, file.BeforeContent, file.Mode); err != nil {\n\t\t\treturn fmt.Errorf(\"恢复自动代码文件 %s 失败: %w\", file.TargetPath, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (task *autoCodeFileTask) cleanup() {\n\tif task != nil && task.stagingDir != \"\" {\n\t\t_ = os.RemoveAll(task.stagingDir)\n\t\ttask.stagingDir = \"\"\n\t}\n}\n\nfunc joinAutoCodeRollbackError(cause, rollbackErr error) error {\n\tif rollbackErr == nil {\n\t\treturn cause\n\t}\n\treturn errors.Join(cause, fmt.Errorf(\"回滚自动代码文件失败: %w\", rollbackErr))\n}\n\nfunc replaceAutoCodeFileAtomically(target string, content []byte, mode fs.FileMode) error {\n\tif mode == 0 {\n\t\tmode = 0o666\n\t}\n\tdir := filepath.Dir(target)\n\tif err := os.MkdirAll(dir, 0o755); err != nil {\n\t\treturn fmt.Errorf(\"创建目标目录 %s 失败: %w\", dir, err)\n\t}\n\ttmp, err := os.CreateTemp(dir, \".autocode-*\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"创建临时文件失败: %w\", err)\n\t}\n\ttmpName := tmp.Name()\n\tdefer os.Remove(tmpName)\n\tif _, err = tmp.Write(content); err == nil {\n\t\terr = tmp.Sync()","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/auto_code_task.go#L238-L274","documentation":"joinAutoCodeRollbackError combines the original commit failure with any rollback failure via errors.Join. When rollback itself failed, the returned error additionally carries 回滚自动代码文件失败 wrapping the rollback error — signaling the workspace may now be in a partially-applied, partially-reverted state. It is a wrapper, not a root cause; always inspect the sibling error(s) in the join for the primary failure.","triggerScenarios":"Any failure inside commitAutoCodeFileTask (apply error, persist() DB error, frontend publish error) whose accompanying task.rollback(applied) also returns an error — e.g. rollback hit a file conflict or filesystem failure.","commonSituations":"DB commit failed AND a generated file was externally modified so rollback stopped mid-way; nested wrappers like 回滚失败 → 文件冲突 appear when errors.Is chains are printed.","solutions":["Read the joined errors in order: the first is the original cause, the second is the rollback failure; fix both conditions","Manually reconcile affected generated files (compare against templates or git) since automatic rollback did not complete","Run the operation again from a clean tree (git checkout the generated paths) after removing the interfering watcher/editor/process"],"exampleFix":"// before: treating the wrapper as the cause\nif strings.Contains(err.Error(), \"回滚自动代码文件失败\") { ... }\n// after: unwrap the joined errors\nfor _, e := range errors.Errors(err) { log.Println(e) }\n// or errors.Is(err, errAutoCodeFileConflict)","handlingStrategy":"try-catch","validationCode":"// no pre-check possible; handle the joined error after the call\nerr := commitAutoCodeFileTask(task, publish, persist)","typeGuard":null,"tryCatchPattern":"err := commitAutoCodeFileTask(task, publish, persist)\nif err != nil {\n    if errors.Is(err, errAutoCodeFileConflict) {\n        // rollback was blocked by an external file change\n    }\n    if joined, ok := err.(interface{ Unwrap() []error }); ok {\n        for _, e := range joined.Unwrap() {\n            log.Printf(\"joined error: %v\", e)\n        }\n    }\n    // reconcile workspace from git before retrying\ngit status --porcelain server/ web/\n}","preventionTips":["Always inspect joined errors with errors.Is/errors.As, never substring matching on the wrapper","Run generation from a clean git tree so partial states are recoverable","Avoid external writers (watchers, formatters) during commitAutoCodeFileTask","Treat this error as 'workspace may be inconsistent' — diff before continuing"],"tags":["go","errors-join","rollback","code-generation"],"backgroundTag":"rollback-failed-partial-state","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}