{"record":{"id":"c6fc25ba5d917c63","repo":"wavetermdev/waveterm","slug":"file-q-already-exists","errorCode":null,"errorMessage":"file %q already exists","messagePattern":"file %q already exists","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshremote/wshremote_file.go","lineNumber":421,"sourceCode":"\t\tif err != nil {\n\t\t\trtn[path] = wshrpc.FileInfo{\n\t\t\t\tPath:          wavebase.ReplaceHomeDir(cleanedPath),\n\t\t\t\tDir:           computeDirPart(cleanedPath),\n\t\t\t\tName:          filepath.Base(cleanedPath),\n\t\t\t\tStatError:     err.Error(),\n\t\t\t\tSupportsMkdir: true,\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\trtn[path] = *fileInfo\n\t}\n\treturn rtn, nil\n}\n\nfunc (impl *ServerImpl) RemoteFileTouchCommand(ctx context.Context, path string) error {\n\tcleanedPath := filepath.Clean(wavebase.ExpandHomeDirSafe(path))\n\tif _, err := os.Stat(cleanedPath); err == nil {\n\t\treturn fmt.Errorf(\"file %q already exists\", path)\n\t}\n\tif err := os.MkdirAll(filepath.Dir(cleanedPath), 0755); err != nil {\n\t\treturn fmt.Errorf(\"cannot create directory %q: %w\", filepath.Dir(cleanedPath), err)\n\t}\n\tif err := os.WriteFile(cleanedPath, []byte{}, 0644); err != nil {\n\t\treturn fmt.Errorf(\"cannot create file %q: %w\", cleanedPath, err)\n\t}\n\treturn nil\n}\n\nfunc (impl *ServerImpl) RemoteFileMoveCommand(ctx context.Context, data wshrpc.CommandFileCopyData) error {\n\tdestUri := data.DestUri\n\tsrcUri := data.SrcUri\n\n\tdestConn, err := connparse.ParseURIAndReplaceCurrentHost(ctx, destUri)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot parse destination URI %q: %w\", srcUri, err)\n\t}","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshremote/wshremote_file.go#L403-L439","documentation":"Returned when the target file already exists and the operation does not overwrite existing files. The path is quoted via %q.","triggerScenarios":"Calling RemoteFileTouchCommand with a path that already exists as a file, directory, or symlink.","commonSituations":"Race where another client created the file first; re-running a script twice; assuming Unix touch semantics (which updates mtime instead of erroring).","solutions":["Check existence first with RemoteFileInfoCommand and skip touch if present.","Delete the existing file if overwrite is intended (RemoteFileDeleteCommand) then touch.","Use a different destination path or add a timestamp suffix."],"exampleFix":"// before\nwshclient.RemoteFileTouchCommand(ctx, p, nil)\n// after\nif _, err := wshclient.RemoteFileInfoCommand(ctx, p, nil); errors.Is(err, fs.ErrNotExist) {\n    wshclient.RemoteFileTouchCommand(ctx, p, nil)\n}","handlingStrategy":"validation","validationCode":"if _, err := wshclient.RemoteFileInfoCommand(ctx, path, nil); err == nil {\n    return nil // already exists, skip touch\n}","typeGuard":null,"tryCatchPattern":"err := wshclient.RemoteFileTouchCommand(ctx, path, nil)\nif err != nil && strings.Contains(err.Error(), \"already exists\") {\n    return nil // idempotent touch\n}","preventionTips":["Make touch calls idempotent by checking existence","Serialize create operations across clients","Do not assume Unix touch update-mtime semantics"],"tags":["filesystem","file-create","conflict","already-exists"],"backgroundTag":"file-already-exists","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}