HarperFast / HarperFast/studio

Sign-up reports expected 409s to Error Tracking — 47 conflicts in 30 days became RUM errors for text the form already shows inline

Open
#1,688 1 comment 0 reactions 0 assignees View on GitHub
rum
Dominant language
TypeScript
Stars
5
Forks
4
Avg merge
1d 8h
Merged PRs (30d)
40

Description

## What

`useSignUp` reports **every** rejection to Error Tracking, including the expected ones the form
already states inline.

[`src/features/auth/hooks/useSignUp.ts:36`](https://github.com/HarperFast/studio/blob/stage/src/features/auth/hooks/useSignUp.ts#L36):

```ts
meta: { skipGlobalErrorToast: true },
// At mutation level, not in the caller's `mutate` callback: React Query skips those when
// the component unmounts mid-flight, and this is the only thing reporting the rejection
// now that `skipGlobalErrorToast` keeps `errorHandler` out of the path.
onError: (error) => console.error(error),
```

The RUM SDK instruments `console.error`, so a `409` on an email that already has an account emits
one Error Tracking event per attempt — and #1668 measured those sessions retrying **~3× each**.
`POST /User/` returned 409 **47 times in the last 30 days**, all of which became RUM errors for
something #1612 deliberately made a piece of inline UI copy.

The comment's reasoning for *where* the handler lives is sound and should stay — a `mutate`
callback is skipped on unmount, so mutation-level is right. What is missing is a filter on *which*
rejections are worth an event.

## Why it is filed separately

Found by the cross-model review on #1685's PR and classified pre-existing. That PR establishes the
opposite norm for the same class on the Domains form — at most one event per submit, and only for
a failure nobody expects (a 5xx or a network failure), never for a 409 the form states inline. The
two forms should agree, but changing sign-up's telemetry is not in that diff's scope.

For context on the norm, `src/features/cluster/domains/addDomainsSequentially.ts` after #1685:

```ts
const unexpected = failures.find(({ error }) => errorStatus(error) !== 409);
if (unexpected) { console.error(unexpected.error); }
```

## Fix

Report only rejections that are not the expected, inline-rendered outcome. `errorStatus` is
exported from `src/react-query/pollUnlessForbidden.ts` for exactly this. The same question applies
to `useForgotPassword` and `useCloudSignIn`, which share the `skipGlobalErrorToast` shape — worth
settling all three together rather than one at a time.

Note the broader number, since it bounds the win: **159 `@error.source:console` events in 30 days
carry a 409**, across every form that routes conflicts through a `console.error`.

## Not this issue

A separate cross-model finding on the same file — `SignUp` keeping a `root` server error across a
resubmit that fails client-side validation — is already #1677.

Contributor guide

Open the contributing guide

Research direction

Start with src/features/auth/hooks/useSignUp.ts and read errorStatus in src/react-query/pollUnlessForbidden.ts, then inspect useForgotPassword and useCloudSignIn for the shared skipGlobalErrorToast pattern. Compare the existing filter in src/features/cluster/domains/addDomainsSequentially.ts. Done means expected 409 rejections are not logged, while unexpected 5xx or network failures still produce one event across all three hooks.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
authentication, frontend, observability
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.