fix(provisioning): retry connect failures and never show an empty error - #1014
Open
posthog[bot] wants to merge 1 commit into
Open
fix(provisioning): retry connect failures and never show an empty error#1014posthog[bot] wants to merge 1 commit into
posthog[bot] wants to merge 1 commit into
Conversation
The three provisioning POSTs had no retry and no network-error handling, so a single failed connect ended the signup run. Worse, when Node's happy-eyeballs connect fails it collapses the per-address failures into an AggregateError whose own `message` is the empty string, and axios copies that empty message onto the AxiosError it rethrows — so the signup screen printed "Failed to create account:" with nothing after the colon, and error tracking got `[""]`. - `src/lib/retry.ts`: extract the bounded retry-with-backoff loop out of `fetch-retry.ts` so both the skills fetches and the provisioning POSTs share one implementation. `fetchWithRetry` keeps its aggregated failure message. - `src/utils/network-errors.ts`: unwrap an error's `errors`/`cause` chain for a usable code and message, decide whether a transport failure is retryable, and build a `NetworkError` that names the host and the remediation. - `provisionNewAccount` retries transient transport failures only. An error carrying a response is never re-POSTed (the server already processed it), and the one retried call that isn't naturally idempotent, `account_requests`, reuses its caller-generated id as the idempotency key. - The three call sites (signup screen, `wizard provision`, CI install) unwrap instead of reading `error.message`, so none of them can print a bare colon. Generated-By: PostHog Code Task-Id: 6645ad7a-b75d-417a-a265-bb9f177968ed
🧙 Wizard CIRun the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands: Test all apps:
Test all apps in a directory:
Test an individual app:
Show more apps
Results will be posted here when complete. |
rafaeelaudibert
marked this pull request as ready for review
July 28, 2026 21:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Someone signing up for PostHog through the wizard could hit a hard crash with a
completely blank error message, ending the run for a user who does not have
an account yet — so the "email already associated → fall back to login" branch
never fires either.
Two causes, same spot:
axios.postcalls inprovisionNewAccounthad a 30s timeout butno retry and no network-error handling, even though the repo already ships
a retry-with-backoff helper in
src/lib/fetch-retry.ts.failures into an
AggregateErrorwhose ownmessageis the empty string,and axios copies that empty message onto the
AxiosErrorit rethrows(
AxiosError.from). Every caller readerror.message, so the signup screenlogged
Failed to create account:with nothing after the colon, and theexception reached error tracking with empty
$exception_values.Changes
src/lib/retry.ts— extract the bounded retry-with-backoff loop out offetch-retry.tsso the skills-server fetches and the provisioning POSTs shareone implementation instead of two.
fetchWithRetrykeeps its existingbehaviour and aggregated failure message.
src/utils/network-errors.ts— walk an error'serrors/causechain fora usable code and message, decide whether a transport failure is worth
retrying, and build a
NetworkErrorwhose message names the host and theremediation (
Couldn't reach us.posthog.com — check your network, VPN, or proxy and try again. (getaddrinfo ENOTFOUND us.posthog.com after 3 attempts)).provisionNewAccountretries transient transport failures only. An errorcarrying a response is never re-POSTed — the server already processed it —
and the one retried call that isn't naturally idempotent,
account_requests,reuses its caller-generated
idas the idempotency key.wizard provision, CI install) unwraprather than reading
error.message, so none of them can print a bare colonagain; the signup screen also reports a non-empty message to error tracking.
Test plan
Reproduced the real failure rather than only mocking it: a hostname resolving to
two addresses that both refuse forces the genuine happy-eyeballs
AggregateError(confirmedmessage: "",code: ECONNREFUSED,errors[0].message: "connect ECONNREFUSED …").Driving the actual signup path (
getOrAskForProjectData({ signup: true }))against it:
Same before/after through
wizard provision, including JSON mode(
{"error":"","code":"provisioning_failed"}→ a populated message with"code":"network_error"). Retries observed taking ~1.5s across 3 attempts.New unit tests cover the retry loop, the unwrapping/formatting, and
provisioning's behaviour on transport failure (retries and recovers, retries all
three POSTs, exhausts to a
NetworkError, and does not retry an HTTP errorresponse or an already-existing account).
pnpm build && pnpm test && pnpm lintall pass — 1659 tests, 0 lint errors.
Created with PostHog Desktop from this inbox report.