Admin general settings form never saves: dotted react-hook-form names nest on input #322

Closed
opened 2026-08-04 10:42:00 +02:00 by fable-5 · 0 comments
Collaborator

Found by Stefan while walking through the self-hosting guide (#320) on a fresh install, confirmed on dorfteich.online: changing the instance name under Admin -> Settings, saving, leaving and re-entering the page shows "Dorfteich" again.

Root cause (reproduced in a jsdom test): the general card and the quota card in AdminSettingsPage.tsx share one useForm whose fields are registered with DOTTED names (register('instance.name') etc.). react-hook-form treats dots as path separators: display works (its get() falls back to the literal flat key from the server data), but typing writes the new value into a NESTED object. handleSubmit therefore produces a body like

{ "instance.name": "Dorfteich",            <- stale flat value
  "instance": { "name": "New Name" } }     <- typed value, unknown key

PATCH /admin/settings validates with a .strict() schema, so the unknown nested key rejects the request (and even without strict, the stale flat keys would write the old values back). The new value never reaches the database.

Affected fields (everything submitted via this form's onSubmit): instance.name, instance.defaultLocale, auth.registrationMode, classification.newPageDefault, classification.uploadPolicy, and the quota.* number fields. Every other card on the page builds its PATCH body by hand with flat keys and is fine.

Why no test caught it: every e2e spec that changes admin settings PATCHes the API directly (collab.spec.ts:139, legal.spec.ts:17, members.spec.ts:25); none drives the general form through the UI.

Fix outline:

  • Make the form submit flat dotted keys again (either register under safe non-dotted aliases with an explicit mapping, or flatten nested objects back to dotted keys on submit, nested values winning over stale flat ones).
  • After a successful save, also invalidate the ['branding'] query so the TopBar picks the new instance name up immediately (it reads /branding with staleTime 5 min; only BrandingManager invalidates it today).
  • Add an e2e that changes the instance name THROUGH the form and asserts it after a reload -- the missing fence.
Found by Stefan while walking through the self-hosting guide (#320) on a fresh install, confirmed on dorfteich.online: changing the instance name under Admin -> Settings, saving, leaving and re-entering the page shows "Dorfteich" again. Root cause (reproduced in a jsdom test): the general card and the quota card in AdminSettingsPage.tsx share one useForm whose fields are registered with DOTTED names (register('instance.name') etc.). react-hook-form treats dots as path separators: display works (its get() falls back to the literal flat key from the server data), but typing writes the new value into a NESTED object. handleSubmit therefore produces a body like { "instance.name": "Dorfteich", <- stale flat value "instance": { "name": "New Name" } } <- typed value, unknown key PATCH /admin/settings validates with a .strict() schema, so the unknown nested key rejects the request (and even without strict, the stale flat keys would write the old values back). The new value never reaches the database. Affected fields (everything submitted via this form's onSubmit): instance.name, instance.defaultLocale, auth.registrationMode, classification.newPageDefault, classification.uploadPolicy, and the quota.* number fields. Every other card on the page builds its PATCH body by hand with flat keys and is fine. Why no test caught it: every e2e spec that changes admin settings PATCHes the API directly (collab.spec.ts:139, legal.spec.ts:17, members.spec.ts:25); none drives the general form through the UI. Fix outline: - Make the form submit flat dotted keys again (either register under safe non-dotted aliases with an explicit mapping, or flatten nested objects back to dotted keys on submit, nested values winning over stale flat ones). - After a successful save, also invalidate the ['branding'] query so the TopBar picks the new instance name up immediately (it reads /branding with staleTime 5 min; only BrandingManager invalidates it today). - Add an e2e that changes the instance name THROUGH the form and asserts it after a reload -- the missing fence.
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#322
No description provided.