Skip to content

Commit 1b26131

Browse files
grdsdevclaude
andcommitted
fix(storage_client): Resolve MultipartRequest finalization error in retry mechanism
When using StorageRetryController, failed uploads would trigger retries that attempted to reuse the same MultipartRequest object. Since MultipartRequest objects become finalized after the first send() call, subsequent retry attempts would throw "Can't finalize a finalized Request" StateError. This fix creates a fresh MultipartRequest for each retry attempt by introducing a createRequest() factory function that generates new request objects with all the necessary headers, files, and fields configured correctly. Fixes the retry functionality for file uploads with StorageRetryController, making it reliable for handling network failures during large file uploads. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent d729fa4 commit 1b26131

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

packages/storage_client/lib/src/fetch.dart

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,21 @@ class Fetch {
159159
StorageRetryController? retryController,
160160
) async {
161161
final headers = options?.headers ?? {};
162-
final request = http.MultipartRequest(method, Uri.parse(url))
163-
..headers.addAll(headers)
164-
..files.add(multipartFile)
165-
..fields['cacheControl'] = fileOptions.cacheControl
166-
..headers['x-upsert'] = fileOptions.upsert.toString();
167-
if (fileOptions.metadata != null) {
168-
request.fields['metadata'] = json.encode(fileOptions.metadata);
169-
}
170-
if (fileOptions.headers != null) {
171-
request.headers.addAll(fileOptions.headers!);
162+
163+
// Create a factory function that generates a fresh MultipartRequest for each attempt
164+
http.MultipartRequest createRequest() {
165+
final request = http.MultipartRequest(method, Uri.parse(url))
166+
..headers.addAll(headers)
167+
..files.add(multipartFile)
168+
..fields['cacheControl'] = fileOptions.cacheControl
169+
..headers['x-upsert'] = fileOptions.upsert.toString();
170+
if (fileOptions.metadata != null) {
171+
request.fields['metadata'] = json.encode(fileOptions.metadata);
172+
}
173+
if (fileOptions.headers != null) {
174+
request.headers.addAll(fileOptions.headers!);
175+
}
176+
return request;
172177
}
173178

174179
final http.StreamedResponse streamedResponse;
@@ -178,6 +183,10 @@ class Fetch {
178183
() async {
179184
attempts++;
180185
_log.finest('Request: attempt: $attempts $method $url $headers');
186+
187+
// Create a fresh request for each retry attempt
188+
final request = createRequest();
189+
181190
if (httpClient != null) {
182191
return httpClient!.send(request);
183192
} else {

0 commit comments

Comments
 (0)