You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The client-side mitigation for #1612 shipped in #1613 and is live in production, and the
outcome it was meant to change has not moved at all. In the last 7 days, 16 of 16
sessions that hit a 409 on POST /User/ retried an average of 2.8 times and not one
of them created an account — statistically identical to the 2.5 retries / 7-of-8
abandonment that motivated the original issue.
The reason is known and recorded in #1613: the 409 handling was deliberately left
status-agnostic because HarperFast/central-manager#630 was going to remove the 409
shortly. That was 19 days ago and #630 is still open, so Studio is running the
narrowed client path against a server that still emits the conflict.
Surfaced by the daily automated RUM review (RUM app f590deee-…, env:prod, windows as noted).
The numbers
POST /User/, production:
Window
409 events
409 sessions
201 events
201 sessions
24h → now
13
5
10
10
48h → 24h
0
0
8
8
72h → 48h
6
2
11
11
7d
45
16
115
115
30d
79
29
193
187
Conversion, measured by session-id set intersection over the 7-day window: 0 of 16.
No session that received a 409 subsequently received a 201 — not on a retry, not later
in the same session.
Before/after the #1613 fix, on the metric the fix targeted:
Volume is also up, not down: #1612 measured "~19 409s in the preceding 30 days total".
It is now 79 in 30 days, and 76 of those 79 fall in the last 14 days.
The per-session signature is unchanged and remarkably uniform — five sessions in the last
24h, each exactly three POST /User/ requests roughly 4.5 s apart, then nothing:
Studio surfaces that text verbatim. SignUp's onError is deliberately status-agnostic
and sets root from describeError(error).message, which for this response resolves to
the RFC 9457 title — i.e. the string the user reads above the submit button is exactly "User already exists". That path is covered by src/features/auth/SignUp.test.tsx (surfaces a %i rejection inline, the 409 case), so
this is confirmed behavior, not inference.
So the person is told, persistently and in the right place, that the account exists — and
still resubmits the same details three times and leaves. The message states a fact and
names no next action; the "Already have an account? Sign in instead." link is below the
form, outside the block their attention is in. #1613 could not add that instruction
because the wording comes from the server and the form maps no status codes by design.
What to do
Ordered by how much each actually changes the outcome:
Ship HarperFast/central-manager#630. It replaces the 409 with a uniform
"check your email to continue" response, which ends the enumeration oracle and the
dead end in one edit — the address either gets an email or gets a "you already have an
account" email, and nobody is left staring at a form. Note its follow-on constraint,
HarperFast/central-manager#636: the uniform response must carry a body, or onSignUpSubmit's if (data) … else throw turns a successful signup into
"Something went wrong".
Interim, status-agnostic, no oracle: render the existing "Already have an account?
Sign in instead." link adjacent to the inline error whenever a submit error is
present. The link is already unconditionally on the page, so promoting it on any
failure leaks nothing new and maps no status codes — it stays within fix(auth): report a failed sign-up in the form, not a fading toast #1613's rule.
Worth doing only if fix(deps): update dependency lucide-react to ^0.542.0 #630 is not imminent; it is a mitigation, not the fix.
I have deliberately not opened a PR re-introducing 409-specific copy. That was
explicitly rejected on review of #1613 (encoding "409 means the address is taken" in the
UI would turn closing the enumeration oracle into "you're removing a helpful message"),
and nothing in this data changes that argument.
Why this is worth reopening the thread rather than waiting
Sign-up is the top of the funnel and this is the only failure mode on it. A third of
sign-up sessions in the last 24h (5 of 15 that submitted) hit it, and the measured
recovery rate across 7 days is zero.
Summary
The client-side mitigation for #1612 shipped in #1613 and is live in production, and the
outcome it was meant to change has not moved at all. In the last 7 days, 16 of 16
sessions that hit a
409onPOST /User/retried an average of 2.8 times and not oneof them created an account — statistically identical to the 2.5 retries / 7-of-8
abandonment that motivated the original issue.
The reason is known and recorded in #1613: the 409 handling was deliberately left
status-agnostic because HarperFast/central-manager#630 was going to remove the 409
shortly. That was 19 days ago and #630 is still open, so Studio is running the
narrowed client path against a server that still emits the conflict.
Surfaced by the daily automated RUM review (RUM app
f590deee-…,env:prod, windows as noted).The numbers
POST /User/, production:Conversion, measured by session-id set intersection over the 7-day window: 0 of 16.
No session that received a 409 subsequently received a
201— not on a retry, not laterin the same session.
Before/after the #1613 fix, on the metric the fix targeted:
Volume is also up, not down: #1612 measured "~19 409s in the preceding 30 days total".
It is now 79 in 30 days, and 76 of those 79 fall in the last 14 days.
The per-session signature is unchanged and remarkably uniform — five sessions in the last
24h, each exactly three
POST /User/requests roughly 4.5 s apart, then nothing:Server latency on these is 0.3–1.8 s, so the gaps are a person waiting for the button to
re-enable and pressing it again.
This is not a deploy gap
Verified rather than assumed:
2bd2f64a,3d1795ad, and4a7b85fd(the sign-up form commits) are all ancestors ofv2.169.3.assets/index-D9wn3O9N.js) matches whathttps://fabric.harper.fast/serves right now.So the
isPendingguard and the persistent inline message are definitely running.Mechanism
The server still answers a duplicate address with a hard conflict —
central-manager/src/resources/user/addUser.js:20:Studio surfaces that text verbatim.
SignUp'sonErroris deliberately status-agnosticand sets
rootfromdescribeError(error).message, which for this response resolves tothe RFC 9457
title— i.e. the string the user reads above the submit button is exactly"User already exists". That path is covered by
src/features/auth/SignUp.test.tsx(surfaces a %i rejection inline, the409case), sothis is confirmed behavior, not inference.
So the person is told, persistently and in the right place, that the account exists — and
still resubmits the same details three times and leaves. The message states a fact and
names no next action; the "Already have an account? Sign in instead." link is below the
form, outside the block their attention is in.
#1613could not add that instructionbecause the wording comes from the server and the form maps no status codes by design.
What to do
Ordered by how much each actually changes the outcome:
"check your email to continue" response, which ends the enumeration oracle and the
dead end in one edit — the address either gets an email or gets a "you already have an
account" email, and nobody is left staring at a form. Note its follow-on constraint,
HarperFast/central-manager#636: the uniform response must carry a body, or
onSignUpSubmit'sif (data) … else throwturns a successful signup into"Something went wrong".
Sign in instead." link adjacent to the inline error whenever a submit error is
present. The link is already unconditionally on the page, so promoting it on any
failure leaks nothing new and maps no status codes — it stays within fix(auth): report a failed sign-up in the form, not a fading toast #1613's rule.
Worth doing only if fix(deps): update dependency lucide-react to ^0.542.0 #630 is not imminent; it is a mitigation, not the fix.
I have deliberately not opened a PR re-introducing 409-specific copy. That was
explicitly rejected on review of #1613 (encoding "409 means the address is taken" in the
UI would turn closing the enumeration oracle into "you're removing a helpful message"),
and nothing in this data changes that argument.
Why this is worth reopening the thread rather than waiting
Sign-up is the top of the funnel and this is the only failure mode on it. A third of
sign-up sessions in the last 24h (5 of 15 that submitted) hit it, and the measured
recovery rate across 7 days is zero.