BaseEntity.Validate() accepts an empty string for a NOT NULL string column, so a required field the form paints red still saves
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 88/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- backend
Research direction
Start in packages/MJCore/src/generic/baseEntity.ts at EntityField.Validate(), then inspect MjFormFieldComponent.IsRequiredEmpty to compare the existing required-field rules. Add tests under packages/MJCore/src/tests/ for empty and whitespace-only values on non-null string fields, while confirming nullable empty strings still pass. Done means validation reports the field name and blocks the save consistently with the form.
Written by the indexing model from the issue text.
Description
Summary
EntityField.Validate() treats an empty string as satisfying a NOT NULL string column, so a required field that the form paints red as "required and empty" still saves — with '' persisted in the column. The UI and the save disagree about the same value.
Repro
MJ next @ 6ac6bcc5ca (6.1.0-edge), Explorer, any entity with a NOT NULL nvarchar column that has no default. Used MJ: AI Agent Request Types → Name (nvarchar(200), AllowsNull = 0, no default).
- Open an existing record, click Edit.
- Clear
Name. The field paints its underline red (mj-forms-field--required-empty) — the form clearly considers it invalid. - Click Save.
Expected: the save is refused with a field-named validation failure, the same way a null would be.
Actual: "Record saved successfully". The row now has Name = '' (LEN(Name) = 0, verified in SQL). Observed live on 2026-09-10 while validating #4355; the record was restored by hand.
Root cause
packages/MJCore/src/generic/baseEntity.ts, EntityField.Validate(), nullability rung:
if (!ef.AllowsNull && (this.Value === null || this.Value === undefined)) {
Only null / undefined fail. '' passes, and SQL Server accepts '' in a NOT NULL column, so nothing downstream catches it either.
The form field takes the opposite view — MjFormFieldComponent.IsRequiredEmpty:
return val === null || val === undefined || val === '';
So the two rules that are supposed to describe the same thing ("this required field has no value") disagree exactly on ''. The new section indicators from #4355 mirror the field rule, so they also flag '' as invalid before save — consistent with the field, inconsistent with Validate() until this is settled.
Proposed fix
Treat an empty (or whitespace-only) string as "missing" for AllowsNull === false string columns in EntityField.Validate():
const missing = this.Value === null || this.Value === undefined
|| (ef.TSType === EntityFieldTSType.String && typeof this.Value === 'string' && this.Value.trim().length === 0);
if (!ef.AllowsNull && missing) { ... }
keeping the existing default-value / new-record carve-out as is. That matches what a user means by a required text field, and it is what the form already promises visually.
If there are entities where an empty string in a NOT NULL column is legitimately meaningful, the alternative is the other direction — stop IsRequiredEmpty from painting '' red — but that seems the less useful contract. Either way the two should agree.
Notes
- Not a regression: the nullability rung has read this way for a long time; #4355 just made the disagreement visible at the section level as well as the field level.
- Test to add alongside the fix:
packages/MJCore/src/__tests__/— a NOT NULL string field set to''and to' 'on an existing record failsValidate()withSource= the field name; a nullable string field set to''still passes.
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 295
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from MemberJunction/MJ
-
next-protect requires only one status check, so PRs merge red and break the branch for everyone Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
MemberJunction/MJ#4609 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
MemberJunction/MJ#4603 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
MemberJunction/MJ#4570 ·
-
bug priority: high
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
MemberJunction/MJ#4548 ·
-
bug priority: high
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
MemberJunction/MJ#4547 ·
All issues in MemberJunction/MJ
Similar issues
-
bug clawsweeper:linked-pr-open clawsweeper:needs-live-repro clawsweeper:no-new-fix-pr impact:message-loss issue-rating: 🐚 platinum hermit P2 regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
AXERA-TECH/ax-llm#77 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
games-on-whales/wolf#509 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100