{"record":{"id":"532ccbedd5d3c53e","repo":"Tencent/WeKnora","slug":"failed-to-open-file-w","errorCode":null,"errorMessage":"failed to open file: %w","messagePattern":"failed to open file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/file/local.go","lineNumber":81,"sourceCode":"\t}\n\tlogger.Infof(ctx, \"Creating directory: %s\", dir)\n\tif err := os.MkdirAll(dir, 0o755); err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to create directory: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to create directory: %w\", err)\n\t}\n\n\t// Generate unique filename using timestamp\n\text := filepath.Ext(file.Filename)\n\tfilename := fmt.Sprintf(\"%d%s\", time.Now().UnixNano(), ext)\n\tfilePath := filepath.Join(dir, filename)\n\tlogger.Infof(ctx, \"Generated file path: %s\", filePath)\n\n\t// Open source file for reading\n\tlogger.Info(ctx, \"Opening source file\")\n\tsrc, err := file.Open()\n\tif err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to open source file: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to open file: %w\", err)\n\t}\n\tdefer src.Close()\n\n\t// Create destination file for writing\n\tlogger.Info(ctx, \"Creating destination file\")\n\tdst, err := os.Create(filePath)\n\tif err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to create destination file: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to create file: %w\", err)\n\t}\n\tdefer dst.Close()\n\n\t// Copy content from source to destination\n\tlogger.Info(ctx, \"Copying file content\")\n\tif _, err := io.Copy(dst, src); err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to copy file content: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to save file: %w\", err)\n\t}","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/local.go#L63-L99","documentation":"SaveFile wraps the error from file.Open() (the multipart/form-data uploaded file handle) when the uploaded file cannot be opened for reading. The original OS error is preserved via %w so callers can inspect os/fs error types. It indicates the upload's in-memory temp file handle is no longer readable.","triggerScenarios":"Calling SaveFile with a *multipart.FileHeader whose Open() fails: the underlying temp file was deleted, the multipart form was consumed/closed before this call, too many open files (EMFILE), or the request body was already drained/aborted by the client.","commonSituations":"Client disconnects mid-upload so the server temp file vanishes; server hits the OS file-descriptor limit under load; middleware closes the request body before the handler saves the file; disk cleanup removes multipart temp files.","solutions":["Check that the request context / multipart form is still valid and the body has not been consumed before calling SaveFile","Raise the file-descriptor limit (ulimit -n) or reduce concurrent uploads if the log shows 'too many open files'","Retry the upload from the client if a disconnect is suspected","Inspect the wrapped error with errors.As for *fs.PathError / syscall errors to pick the right fix"],"exampleFix":"// before\nsrc, err := file.Open()\nif err != nil {\n\treturn \"\", fmt.Errorf(\"failed to open file: %w\", err)\n}\n// after: verify the handle early and surface a clearer message\nsrc, err := file.Open()\nif err != nil {\n\tlogger.Errorf(ctx, \"uploaded file unreadable (client disconnect?): %v\", err)\n\treturn \"\", fmt.Errorf(\"failed to open uploaded file: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"src, err := fileHeader.Open()\nif err != nil {\n\tif errors.Is(err, fs.ErrNotExist) {\n\t\t// multipart temp file gone: ask client to re-upload\n\t}\n\treturn fmt.Errorf(\"failed to open file: %w\", err)\n}","preventionTips":["Call SaveFile before any middleware closes or re-reads the request body","Monitor 'too many open files' errors and raise ulimit -n on busy servers","Validate multipart form presence before handling files","Log the wrapped error, not just the message, to distinguish disconnects from FD exhaustion"],"tags":["go","file-io","upload","filesystem"],"backgroundTag":"file-open-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}