From 4235aa4fe5c6da719e9c7926e52b5330488db26f Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 5 Jun 2026 12:30:53 +0100 Subject: [PATCH] protondrive: fix long hangs on permanent validation failures shouldRetry treated every Code=200501 API error as a transient storage block error and retried it. Proton also returns Code=200501 with an HTTP 422 for permanent validation failures (e.g. a content key packet that cannot be verified, or an upload format the account is not enabled for), so these were retried until the operation timed out causing a multi-minute hang. This fixes it by only retrying Code=200501 when it is not a permanent client (4xx) error. --- backend/protondrive/protondrive.go | 11 ++++++++--- backend/protondrive/protondrive_internal_test.go | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/backend/protondrive/protondrive.go b/backend/protondrive/protondrive.go index 9188383cf..4595ea5dc 100644 --- a/backend/protondrive/protondrive.go +++ b/backend/protondrive/protondrive.go @@ -264,9 +264,14 @@ func shouldRetry(ctx context.Context, err error) (bool, error) { } var apiErr *proton.APIError if errors.As(err, &apiErr) { - // Transient storage block error ("Please retry"). - if apiErr.Code == 200501 { - fs.Debugf(nil, "Retrying storage block error: %v", err) + // Code 200501 is a generic Drive operation-failure code. Proton also + // returns it with an HTTP 422 for permanent validation failures (for + // example a content key packet that cannot be verified, or an upload + // format the account is not enabled for), which must NOT be retried - + // doing so spins the pacer until the operation times out. Only retry it + // when it is not a permanent client (4xx) error. + if apiErr.Code == 200501 && (apiErr.Status < 400 || apiErr.Status >= 500) { + fs.Debugf(nil, "Retrying transient storage block error: %v", err) return true, err } // Server errors. 503 is already handled by the SDK; retry the rest. diff --git a/backend/protondrive/protondrive_internal_test.go b/backend/protondrive/protondrive_internal_test.go index aaf2945ae..d1ef4224d 100644 --- a/backend/protondrive/protondrive_internal_test.go +++ b/backend/protondrive/protondrive_internal_test.go @@ -77,7 +77,8 @@ func TestShouldRetry(t *testing.T) { }{ {"nil error", ctx, nil, false}, {"cancelled context", cancelledCtx, errors.New("some error"), false}, - {"storage block error Code=200501", ctx, apiErr(422, 200501), true}, + {"permanent validation error Code=200501 Status=422 (not retried)", ctx, apiErr(422, 200501), false}, + {"transient storage block error Code=200501 Status=500 (retried)", ctx, apiErr(500, 200501), true}, {"server error Status=500", ctx, apiErr(500, 0), true}, {"server error Status=502", ctx, apiErr(502, 0), true}, {"server error Status=504", ctx, apiErr(504, 0), true},