{"record":{"id":"7ad7bd05152a16b9","repo":"Tencent/WeKnora","slug":"failed-to-open-file-w-7ad7bd","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/obs.go","lineNumber":164,"sourceCode":"\t}\n\treturn \"obs://\"\n}\n\nfunc (s *obsFileService) SaveFile(ctx context.Context,\n\tfile *multipart.FileHeader, tenantID uint64, knowledgeID string,\n) (string, error) {\n\text := filepath.Ext(file.Filename)\n\n\tvar objectKey string\n\tif s.pathPrefix != \"\" {\n\t\tobjectKey = fmt.Sprintf(\"%s/%d/%s/%s%s\", s.pathPrefix, tenantID, knowledgeID, uuid.New().String(), ext)\n\t} else {\n\t\tobjectKey = fmt.Sprintf(\"%d/%s/%s%s\", tenantID, knowledgeID, uuid.New().String(), ext)\n\t}\n\n\tsrc, err := file.Open()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to open file: %w\", err)\n\t}\n\tdefer src.Close()\n\n\tcontentType := file.Header.Get(\"Content-Type\")\n\tif contentType == \"\" {\n\t\tcontentType = \"application/octet-stream\"\n\t}\n\n\t_, err = s.client.PutObject(ctx, &s3.PutObjectInput{\n\t\tBucket:        aws.String(s.bucketName),\n\t\tKey:           aws.String(objectKey),\n\t\tBody:          src,\n\t\tContentLength: aws.Int64(file.Size),\n\t\tContentType:   aws.String(contentType),\n\t\t// ACL:           \"private\",\n\t})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to upload file to OBS: %w\", err)","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/obs.go#L146-L182","documentation":"SaveFile wraps the error from file.Open() (multipart.FileHeader.Open) when the uploaded file handle cannot be opened. This happens after the multipart form was parsed but before any OBS upload, so nothing was written to the bucket.","triggerScenarios":"Calling SaveFile with a *multipart.FileHeader whose underlying reader cannot be opened — typically a temp file that was removed, or a corrupted multipart part in the HTTP request.","commonSituations":"Server tmp dir cleaned mid-request (systemd-tmpfiles, /tmp cleanup); very large uploads spilling to disk then failing to reopen; request body truncated/timed out before Open.","solutions":["Inspect the wrapped error (%w) — if it is os.ErrNotExist, the multipart temp file vanished; re-upload instead of retrying Open","Check the server's temp directory exists, is writable, and is not aggressively cleaned during requests","Ensure the client request completes fully (timeouts, Content-Length) so the multipart part is intact","Return 4xx/5xx to the client prompting re-upload rather than retrying server-side"],"exampleFix":"// before\nsrc, err := file.Open()\nif err != nil { return \"\", fmt.Errorf(\"failed to open file: %w\", err) }\n// after\nsrc, err := file.Open()\nif err != nil {\n    if errors.Is(err, fs.ErrNotExist) {\n        return \"\", fmt.Errorf(\"upload temp file lost, re-upload required: %w\", err)\n    }\n    return \"\", fmt.Errorf(\"failed to open file: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"if file == nil || file.Size == 0 {\n    return errors.New(\"empty or missing upload part\")\n}","typeGuard":null,"tryCatchPattern":"path, err := svc.SaveFile(ctx, tenantID, kid, fh)\nif err != nil {\n    if errors.Is(err, fs.ErrNotExist) || strings.Contains(err.Error(), \"failed to open file\") {\n        http.Error(w, \"upload corrupted, please retry\", http.StatusBadRequest)\n        return\n    }\n    http.Error(w, \"upload failed\", http.StatusInternalServerError)\n}","preventionTips":["Do not disable or over-clean the multipart temp directory during request handling","Set sane client/server upload timeouts so requests complete","Distinguish open-failures (client re-upload) from upload-failures (server-side retry)"],"tags":["multipart","file-upload","io"],"backgroundTag":"file-open-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}