Classify transport errors precisely, make base errors unwrappable, and fix backoff jitter
I maintainer di solito rispondono entro 1 giorno
@ffumero2003 ci sta già lavorando.
Dal 8/11/2026.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- go
- Ambito
- backend-api-design
Direzione di ricerca
Start with the named sections in base/base.go and internal/retry/retry.go, then inspect b2/backend.go where positive backoff values are handled. Read the existing retry and error classification behavior first; the acceptance criteria specify the required error wrapping, retry decisions, Retry-After handling, and jitter tests.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Context
base turns every non-HTTP failure other than a certificate verification error into the same b2err{retry: 1} and keeps only the error text. Effects:
- Cause is lost.
b2errhas noUnwrap, soerrors.Is(err, context.DeadlineExceeded),errors.As(err, &netErr)and similar checks are false for errors frombaseandb2. - Wrapped context errors are retried. Cancellation is detected by identity comparison, so a
RoundTripperthat wraps errors (tracing, metrics) turns a deadline into a retryable error. - Deterministic failures are retried five times: invalid header values (CR/LF in
UserAgent) and unsupported schemes. - Fixed 1 s delay for network errors, and
internal/retryJitteradds only about 1-3%. - Retry-After makes any status retryable when numeric (clamped to 1-30 s), and the HTTP-date form is ignored.
- Type assertions (
err.(b2err)) inAction,Code,MsgCode,MaxRetries,MaxReuploadsandBackoffclassify a wrappedb2errasPuntwith code 0.
Certificate verification failures already return the original error and are not retried (Backblaze/blazer#139). A 408 on a non-upload call is retried since Backblaze/blazer#167 (merged).
Current behavior
At a5e0d13: base/base.go:518-558 (transport error handling; identity check at 521-525, retry: 1 at 552-556), :48-61 (no Unwrap), :69-74 (any retry > 0 is Retry), :166-174 and :184-196 (Retry-After parsed as integer seconds only), :230-242 (Backoff); type assertions at :65, :111, :120, :201, :214, :231; b2/backend.go:1066-1076 (positive backoff replaces the exponential delay); internal/retry/retry.go:73-78 (Jitter).
Reproduced locally at a5e0d13:
refused connection: As(net.Error)=false Action=Retry Backoff=1s
unsupported scheme (ftp): Action=Retry MaxRetries=5
UserAgent with CR/LF: invalid header field value Action=Retry
wrapping transport, deadline: Is(DeadlineExceeded)=false Action=Retry
400 with Retry-After: 3: Action=Retry
fmt.Errorf("%w", 503 b2err): Action=Punt
Expected behavior
Callers can use errors.Is/errors.As; configuration errors fail at once; network retries back off with real jitter.
Acceptance criteria
- R1. A deadline through a wrapping
RoundTrippersatisfieserrors.Is(err, context.DeadlineExceeded)and isPunt. - R2. A refused connection satisfies
errors.As(err, &netErr); an invalid header value or unsupported scheme is not retried. - R3. An HTTP-date
Retry-Afteron a 503 is honored (capped);Retry-Afteron a 400 does not make it retryable. - R4. A
b2errwrapped withfmt.Errorf("%w")keeps its classification. - R5. New
internal/retrytests show growing, capped delays that differ across calls by more than 10%.
In scope
Proposed change
- Add
Unwrap() errortob2err, useerrors.Isfor context checks, and export a typed error (for example*base.APIErrorwithStatus,Code,Message,Method). - Use
errors.Asin all classification helpers. - Classify context and request-construction errors as
Punt; keep dial errors, resets and timeouts retryable, subject to whether the method is safe to repeat. - Keep
retryfor a realRetry-After, parse both forms (keeping the 30 s cap), and honor it only for 429 and 503. - Use full or equal jitter in
internal/retryand the same exponential schedule for network errors. - Validate
UserAgentwhen the option is set.
Out of scope
- Unrelated work outside the components and behavior described in In scope.
Verification
Run the repository regression checks with live credentials unset:
unset B2_APPLICATION_KEY_ID B2_APPLICATION_KEY B2_ACCOUNT_ID B2_ACCOUNT_KEY
go build ./...
go vet ./...
go test -race -count=1 ./base ./b2/... ./internal/retry
- Exercise wrapped deadlines, refused connections, invalid headers/schemes, wrapped API errors, and the stated
Retry-Afterstatus/date cases; assert errors.Is/errors.As and literal classifications. - Measure the retry schedule through the existing test controls and assert growth, cap, and the stated >10% jitter variation; demonstrate each targeted regression red then green.
- Expected result: the checks above succeed and the observable outcomes in Acceptance criteria are demonstrated. If a check cannot run, report
Could not run because: ...; if it starts but fails, reportCould not complete because: .... A skipped check is not a pass.
Links
Backblaze/blazer#101 (401 classification). Backblaze/blazer#18 and #31 bounded the retry count. Backblaze/blazer#139 stopped retrying certificate verification failures. Backblaze/blazer#167 (merged, closes #165) made 408 retryable on non-upload calls and did not change retry counts or backoff timing.
- Lingua principale
- Go
- Stelle
- 66
- Fork
- 18
- Merge medio
- 1g 10h
- PR unite (30g)
- 132
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Backblaze/blazer
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
Bucket.Attrs never returns ReplicationConfig: replication configuration is write-onlyForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
test: skip the fuzz non-vacuity guard when replaying a single seedForse già presa @ffumero2003 l’ha presa 5 giorni fa. Apertatesting
Backblaze/blazer#330 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di Backblaze/blazer
Issue simili
-
needs-triage typo
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
llm-d-incubation/llm-d-scaling-manager#122 ·
I maintainer di solito rispondono entro 1 giorno
-
good first issue severity: low tech-debt
Difficoltà 2/5 Mezza giornata Idoneità per principianti 75/100
TMHSDigital/subenum#329 ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug] Backend summarize min() / max() panics when a field has no numeric valuesForse già presa @weng5e l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
grafana/grafana-infinity-datasource#1832 ·
I maintainer di solito rispondono entro 1 giorno
-
tech-debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
GillMacedo/godebugdiff#13 ·