fix(user): make getNextRef Postgres-compatible#3749
Closed
Blume1977 wants to merge 1 commit into
Closed
Conversation
The `LIKE '%[0-9]-[0-9]%'` filter in UserRepository.getNextRef relied on MSSQL character-class syntax. On Postgres, `[0-9]` is a literal 5-char sequence, so the query matched no rows. findOne returned null and the chained `.then((u) => +u.ref.replace(...) + 1)` threw a TypeError every time setUserRef ran for a user without a ref on a userData with kycLevel >= 50. Since develop->main released the PSQL migration to prod, this has been crashing every caller of setUserRef: new user creation on KYC50+ userData, admin updateUser with setRef=true, KYC level bumps to >= 50, updatePersonalData on KYC50+ userData, and the mergeUserData activation loop. The merge case is especially visible because the V8 TypeError text reaches end users via ApiExceptionFilter and the DFX-Services frontend. Replace the MSSQL LIKE with a Postgres POSIX regex on the column, and guard the deref so a future empty-result state does not reintroduce the same crash shape.
|
Member
|
Duplicate of #3748 |
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.
Summary
UserRepository.getNextRefqueries the highest existing user ref:[0-9]is an MSSQL character class. On Postgres it is a literal sequence of five characters ([,0,-,9,]), so the query matches no rows.findOnereturnsnull, and the chained.then((u) => +u.ref.replace('-', '') + 1)throwsTypeError: Cannot read properties of null (reading 'ref').Since #3746 deployed develop → main (2026-05-22 ~01:06 UTC), every caller of
UserRepository.setUserRefon a userData withkycLevel >= 50has been crashing in production:UserService.createUser(user.service.ts:307)UserService.updateUserwithsetRef:true(user.service.ts:402)UserDataService.updateKyc(user-data.service.ts:351)UserDataService.updatePersonalData(user-data.service.ts:541)UserDataService.mergeUserDataactivation loop (user-data.service.ts:1363/1367)The merge path is especially user-visible: the V8 TypeError text leaks to clients via
ApiExceptionFilter(shared/filters/exception.filter.ts:25) and the DFX-Services frontend displays it verbatim onservices.dfx.swiss/account-merge?otp=…. BecausemergeUserDatais non-transactional and the crash fires afteruserDataRepo.save(master), the merge leaves a half-committed state (new user attached,ref=NULL, AccountMergeis_completed=false).Change
Single file, single function. Swap MSSQL character-class LIKE for a Postgres POSIX regex on the column, and add a null-safe fallback for the empty-result case.
The grep of the codebase confirms this is the only remaining MSSQL-LIKE-character-class pattern after #3745 cleaned up the boolean comparisons.
Test plan
npx prettier --write— no formatting changesnpx eslint— no warningsnpx tsc --noEmit— cleannpx jest src/subdomains/generic/user/— 33/33 passnpx jest(full suite) — 926 passed, 106 skipped, 0 failedgetNextRefproduces a sane next refCherry-pick path
Production is currently broken for KYC50+ operations. Once this lands on develop, please cherry-pick or release-roll to
mainASAP. The change is one file, no migration, no env change, no DTO/contract change — safe to fast-track.Follow-ups (out of scope here, separate PRs)
ApiExceptionFilterinfo-disclosure —shared/filters/exception.filter.ts:25passes rawexception.messageto clients on 500s. Should return a generic message and log the detail server-side.mergeUserDatatransactional — wrap the whole sequence in a TypeORM transaction so future mid-merge crashes don't leave half-committed state (slave MERGED + master partially updated + new user without ref + AccountMerge not completed).POST /v1/realunit/register/wallet— existing-DFX-customers who hit a failed merge get routed byKycCubitto the empty new-user registration form (_registrationSignProduced=false+ no Wallet-Status check). They should land on a re-sign screen that callsregister/walletwith the existing account data.Cleanup for already-affected accounts
Customers who hit the crash since 01:06 UTC have a partial state. Per-account fix-up:
Then trigger
POST /v1/realunit/register/walletfrom the affected wallet to create the per-walletREALUNIT_REGISTRATIONstep so Buy is unlocked.