{"record":{"id":"7bb7196ad6837504","repo":"vxcontrol/pentagi","slug":"failed-to-write-temporary-upload-file-w","errorCode":null,"errorMessage":"failed to write temporary upload file: %w","messagePattern":"failed to write temporary upload file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/flowfiles/files.go","lineNumber":333,"sourceCode":"}\n\nfunc SaveUploadedFileToTemp(fh *multipart.FileHeader, dir string) (string, error) {\n\tsrc, err := fh.Open()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to open uploaded file: %w\", err)\n\t}\n\tdefer src.Close()\n\n\tdst, err := os.CreateTemp(dir, \".upload-*\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create temporary upload file: %w\", err)\n\t}\n\ttmpPath := dst.Name()\n\tdefer dst.Close()\n\n\tif _, err := io.Copy(dst, src); err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn \"\", fmt.Errorf(\"failed to write temporary upload file: %w\", err)\n\t}\n\tif err := dst.Chmod(0644); err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn \"\", fmt.Errorf(\"failed to set temporary upload file permissions: %w\", err)\n\t}\n\n\treturn tmpPath, nil\n}\n\nfunc IsWithinDir(absPath, dir string) bool {\n\treturn strings.HasPrefix(\n\t\tfilepath.Clean(absPath)+string(filepath.Separator),\n\t\tfilepath.Clean(dir)+string(filepath.Separator),\n\t)\n}\n\nfunc ResolvePulledStagedTarget(stagingDir, cacheRelPath string) string {\n\tcandidates := []string{","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/flowfiles/files.go#L315-L351","documentation":"After creating the temp file, SaveUploadedFileToTemp copies the multipart source into it with io.Copy. If the copy fails mid-stream, the partially written temp file is removed (os.Remove) and this error is returned with the underlying cause (client disconnect, disk full, read error on the multipart stream).","triggerScenarios":"io.Copy(dst, src) returns an error during UploadFlowFiles: the HTTP client disconnected mid-upload (broken pipe / context cancel), the disk filled while writing, or reading from the multipart.FileHeader failed.","commonSituations":"Users canceling large uploads; reverse proxies (nginx) timing out and dropping the connection; small container disk quotas exceeded by a big file; network interruption between proxy and backend.","solutions":["Check whether the wrapped error is syscall.EPIPE / 'unexpected EOF' — the client disconnected; treat as benign client-abort and log at info level.","Free disk space or raise the volume quota for the temp/upload directory.","Increase reverse-proxy (nginx client_body_timeout / proxy_read_timeout) and body size limits for large uploads.","Retry the upload client-side on transient network errors; the temp file is cleaned up automatically."],"exampleFix":"// before\ntmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, dir)\nif err != nil {\n    return err\n}\n// after\ntmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, dir)\nif err != nil {\n    if errors.Is(err, syscall.EPIPE) || errors.Is(err, io.ErrUnexpectedEOF) {\n        log.Info().Err(err).Msg(\"client aborted upload\")\n        return nil\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// Pre-check rough size before streaming if the request declares Content-Length:\nif r.ContentLength > maxAllowedUpload {\n    http.Error(w, \"file too large\", http.StatusRequestEntityTooLarge)\n    return\n}","typeGuard":null,"tryCatchPattern":"tmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, dir)\nif err != nil {\n    if errors.Is(err, syscall.EPIPE) || errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.Canceled) {\n        log.Info().Err(err).Msg(\"upload aborted by client\") // temp file already cleaned up\n        return\n    }\n    if errors.Is(err, syscall.ENOSPC) {\n        http.Error(w, \"storage full\", http.StatusInsufficientStorage)\n        return\n    }\n    http.Error(w, \"upload failed\", http.StatusInternalServerError)\n    return\n}","preventionTips":["Enforce max upload size at the proxy and in handler before reading the body.","Keep generous disk headroom on the temp/upload volume; monitor with alerts.","Tune nginx/proxy read timeouts to exceed expected upload durations.","Remember the function removes the partial temp file — never reuse tmpPath after an error."],"tags":["io","filesystem","upload","disk-full"],"backgroundTag":"disk-full-write-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}