#4345·civitai

userProfile.update: showcaseItems has no server-side length bound

Author: ZacxDevCreated Aug 24, 2026Updated Aug 24, 2026

userProfile.update accepts a showcaseItems array of any length. The client caps it at 32; the server schema does not, so the two disagree and the cap is only advisory.

Where

src/server/schema/user-profile.schema.ts:66

typescript
showcaseItems: z.array(showcaseItemSchema).optional(),

No .max(), and this is the input schema for update: guardedProcedure (src/server/routers/user-profile.router.ts:30).

The limit that does exist is client-side only

  • src/server/common/constants.ts:362showcaseItemsLimit: 32
  • src/components/Profile/ShowcaseItemsInput.tsx:94if (showcaseItems.length >= limit) stops the user adding a 33rd item in the UI
  • src/components/Modals/UserProfileEditModal.tsx:830 — the copy tells the user "Select up to 32 items"

So the 32 is enforced in the editor, not on the write path.

It is stored unbounded

In updateUserProfile (src/server/services/user-profile.service.ts:221), showcaseItems is not destructured out — it falls into the ...profile rest and is written straight through:

typescript
data: {
  ...profile,
  ...
}

There is no length check between the tRPC input and the userProfile row.

Suggested fix

Bound it in the schema so the server agrees with the client:

typescript
showcaseItems: z.array(showcaseItemSchema).max(constants.profile.showcaseItemsLimit).optional(),

Worth noting that addEntityToShowcase — the other way items get added — already truncates to the same constant, so the schema bound would make the two entry points consistent rather than introducing a new rule.

Why file it rather than leave a comment

Any oversized showcase already stored keeps rendering normally, so there is no user-visible symptom that would prompt someone to notice this. A code comment next to the schema line would be the obvious alternative, but nothing would ever surface it again, hence an issue.