{"record":{"id":"0ee706c5967d33db","repo":"flipped-aurora/gin-vue-admin","slug":"w-s","errorCode":null,"errorMessage":"%w: %s","messagePattern":"%w: %s","errorType":"exception","errorClass":"errAutoCodeDuplicateTarget","httpStatus":null,"severity":"error","filePath":"server/service/system/auto_code_task.go","lineNumber":96,"sourceCode":"\t\tstagingDir: stagingDir,\n\t\tfiles:      make([]autoCodeTaskFile, 0, len(files)),\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\ttask.cleanup()\n\t\t}\n\t}()\n\n\ttargets := make([]string, 0, len(files))\n\tnormalizedFiles := make(map[string][]byte, len(files))\n\tfor target, content := range files {\n\t\tabsoluteTarget, absoluteErr := filepath.Abs(target)\n\t\tif absoluteErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"解析目标路径 %q 失败: %w\", target, absoluteErr)\n\t\t}\n\t\tcleanTarget := filepath.Clean(absoluteTarget)\n\t\tif _, exists := normalizedFiles[cleanTarget]; exists {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", errAutoCodeDuplicateTarget, cleanTarget)\n\t\t}\n\t\tif _, classifyErr := layout.classify(cleanTarget); classifyErr != nil {\n\t\t\treturn nil, classifyErr\n\t\t}\n\t\tnormalizedFiles[cleanTarget] = content\n\t\ttargets = append(targets, cleanTarget)\n\t}\n\tsort.Slice(targets, func(i, j int) bool {\n\t\tleftKind, _ := layout.classify(targets[i])\n\t\trightKind, _ := layout.classify(targets[j])\n\t\tif leftKind != rightKind {\n\t\t\treturn leftKind == autoCodeTaskBackend\n\t\t}\n\t\treturn targets[i] < targets[j]\n\t})\n\n\tfor index, target := range targets {\n\t\tkind, _ := layout.classify(target)","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/auto_code_task.go#L78-L114","documentation":"This error is returned by prepareAutoCodeFileTask when the caller submitted two or more target file paths that resolve to the same cleaned absolute path. The duplicate-target sentinel errAutoCodeDuplicateTarget (\"自动代码任务包含重复目标\") is wrapped with the offending path, so callers can detect it with errors.Is. It protects the staging/commit pipeline from processing the same file twice with conflicting contents.","triggerScenarios":"Calling Create (which routes to prepareRequestFileTask -> prepareAutoCodeFileTask) with a files map or request containing two entries whose paths differ textually but normalize to the same target after filepath.Abs + filepath.Clean — e.g. './server/main.go' and 'server/main.go', or paths containing redundant separators or '..' segments.","commonSituations":"Client-side code builds the file list by concatenating backend and frontend generation outputs where the same path can appear in both lists; templates that emit both an existing file and a generated file for the same location; manual API calls with copied paths differing only by a './' prefix or trailing separators.","solutions":["Deduplicate the requested file paths before calling Create, keeping one entry per cleaned absolute path (e.g. via filepath.Clean/filepath.Abs on each key).","Check the request payload on the frontend side for paths that differ only in normalization ('./' prefix, '..' segments, duplicate slashes) and merge them.","If two different contents are genuinely intended for one path, decide on one and remove the other — the task cannot reconcile conflicting contents.","In tests or tooling, verify with errors.Is(err, system errAutoCodeDuplicateTarget) to surface which path was duplicated (it is appended after the sentinel message)."],"exampleFix":"// before\nfiles := map[string][]byte{\n  \"./server/service/foo.go\": contentA,\n  \"server/service/foo.go\":   contentB, // duplicate after Clean\n}\n// after\nfiles := map[string][]byte{\n  \"server/service/foo.go\": contentA, // single normalized entry\n}","handlingStrategy":"validation","validationCode":"func validateNoDuplicateTargets(paths []string) error {\n  seen := make(map[string]struct{}, len(paths))\n  for _, p := range paths {\n    abs, err := filepath.Abs(p)\n    if err != nil {\n      return err\n    }\n    clean := filepath.Clean(abs)\n    if _, dup := seen[clean]; dup {\n      return fmt.Errorf(\"duplicate target: %s\", clean)\n    }\n    seen[clean] = struct{}{}\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":"// Go: detect the sentinel after a Create call\nif err := svc.Create(c, req); err != nil {\n  if errors.Is(err, system.ErrAutoCodeDuplicateTarget) {\n    // surface the duplicated path appended in the message\n    return fmt.Errorf(\"request contains a duplicated target: %v\", err)\n  }\n  return err\n}","preventionTips":["Normalize every target with filepath.Abs + filepath.Clean before adding it to the request's file map.","Build the file list in a single pass over a map keyed by cleaned absolute path so duplicates collapse automatically.","When merging backend and frontend generation outputs, dedupe on the cleaned path rather than the raw string."],"tags":["go","duplicate-target","path-normalization","autocode"],"backgroundTag":"duplicate-file-target","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}