{"record":{"id":"0dd3021060465f5e","repo":"OpenNHP/opennhp","slug":"could-not-copy-file-to-server-v","errorCode":null,"errorMessage":"could not copy file to server: %v","messagePattern":"could not copy file to server: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/db/utils.go","lineNumber":237,"sourceCode":"\n\tstartTime := time.Now()\n\n\tbody := &bytes.Buffer{}\n\twriter := multipart.NewWriter(body)\n\n\tpart, err := writer.CreateFormFile(\"file\", filepath.Base(filePath))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not create form file: %v\", err)\n\t}\n\n\tprogressReader := &ProgressReader{\n\t\tReader:   file,\n\t\tProgress: progress,\n\t}\n\n\t_, err = io.Copy(part, progressReader)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not copy file to server: %v\", err)\n\t}\n\n\terr = writer.Close()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not close writer: %v\", err)\n\t}\n\n\tuploadUrl := httpHost + \"storage/upload\"\n\n\treq, err := http.NewRequest(\"POST\", uploadUrl, body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not create request: %v\", err)\n\t}\n\n\treq.Header.Set(\"Content-Type\", writer.FormDataContentType())\n\n\tclient := &http.Client{\n\t\tTimeout: 120 * time.Minute,","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/db/utils.go#L219-L255","documentation":"After creating the form part, the file is streamed into the multipart body with io.Copy(part, progressReader). The error 'could not copy file to server: %v' wraps an io.Copy failure — typically a read error from the source file (I/O error, file removed/truncated mid-read) or a write error into the in-memory body (allocation failure). Despite the wording, at this stage nothing has been sent to the server; the copy is into a local buffer.","triggerScenarios":"Calling UploadFileToNHPServer when the source file experiences a read I/O error mid-copy (disk failure, file truncated concurrently, NFS hiccup), or the process runs out of memory growing bytes.Buffer for a very large file.","commonSituations":"Uploading multi-gigabyte ZTDO files into an in-memory buffer on a memory-limited host; disk errors on the source volume; another process truncating the file during upload; OOM killer pressure.","solutions":["Check the wrapped error: read errors indicate source file/disk problems, write/allocation errors indicate memory exhaustion","For very large files, ensure the host has RAM roughly equal to the file size, since body is an in-memory bytes.Buffer","Verify the file is not being modified or truncated during upload","Check disk health (dmesg / smartctl) for I/O errors on the source volume","Consider chunked or streaming uploads (io.Pipe into http.NewRequest) for large files"],"exampleFix":"// before\nbody := &bytes.Buffer{}\nwriter := multipart.NewWriter(body)\n// after\n// stream large files instead of buffering entirely in memory\npr, pw := io.Pipe()\nwriter := multipart.NewWriter(pw)\ngo func() {\n    defer pw.Close()\n    part, _ := writer.CreateFormFile(\"file\", filepath.Base(filePath))\n    io.Copy(part, progressReader)\n    writer.Close()\n}()\nreq, _ := http.NewRequest(\"POST\", uploadUrl, pr)","handlingStrategy":"try-catch","validationCode":"info, err := os.Stat(path)\nif err != nil {\n    return err\n}\nif uint64(info.Size()) > maxInMemoryUploadBytes {\n    return fmt.Errorf(\"file too large for in-memory upload buffer (%d bytes)\", info.Size())\n}","typeGuard":"func fitsInMemory(path string, limit int64) bool {\n    info, err := os.Stat(path)\n    return err == nil && info.Size() <= limit\n}","tryCatchPattern":"url, err := dev.UploadFileToNHPServer(filePath)\nif err != nil {\n    if strings.Contains(err.Error(), \"could not copy file to server\") {\n        return fmt.Errorf(\"local copy into multipart body failed (read or OOM), no data was sent: %w\", err)\n    }\n    return err\n}","preventionTips":["Do not modify or truncate the file while the upload is in progress","For large files, stream via io.Pipe into http.NewRequest instead of bytes.Buffer","Monitor process memory; the whole body is buffered in RAM","Check source disk health when read errors recur"],"tags":["go","io","multipart","file-upload","memory"],"backgroundTag":"file-read-failed","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}