Skip to content

Fix: Prevent creating empty or duplicate fields #15168

Merged
Siedlerchr merged 22 commits into
JabRef:mainfrom
pluto-han:fix-for-issue-15130
Feb 24, 2026
Merged

Fix: Prevent creating empty or duplicate fields #15168
Siedlerchr merged 22 commits into
JabRef:mainfrom
pluto-han:fix-for-issue-15130

Conversation

@pluto-han

@pluto-han pluto-han commented Feb 19, 2026

Copy link
Copy Markdown
Collaborator

Related issues and pull requests

Closes #15130

PR Description

This PR addresses the issue where empty and duplicate fields can be created. When checking duplication, use equalsIgnoreCase instead of equals. After creating a new field, it will scroll to and highlight newly added field.

Required verification screenshot:
image

Steps to test

  1. Open File -> Preference -> Entry types

  2. Select an entry type, type some spaces or a string with spaces (e.g. "te st") or leave field empty. Click "+" or press enter.

  3. Expected result: No fields are created, JabRef warns users "Fields cannot be empty and must not contain spaces."

  4. Type "test" and save. Then type "test" again, click "+" or press enter.

  5. Expected result: A pop-up warning shows up: You added field "test" twice. Only one will be kept.

image image

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • I added JUnit tests for changes (if applicable)
  • I added screenshots in the PR description (if change is visible to the user)
  • I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository

@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Prevent empty, duplicate, and invalid field creation in custom entry types

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Prevent creation of empty fields and fields containing spaces with validation
• Prevent duplicate field creation using case-insensitive comparison
• Capitalize first letter of custom field names in display
• Scroll to and highlight newly added fields in the UI

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/CustomEntryTypesTab.java ✨ Enhancement +9/-2

Add field validation and scroll to new fields

• Changed addNewField action handler to call local method instead of viewModel method
• Added validation check before adding new field
• Modified addNewField() method to handle Optional return and scroll to newly added field

jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/CustomEntryTypesTab.java


2. jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/CustomEntryTypesTabViewModel.java 🐞 Bug fix +14/-9

Implement duplicate field detection and return newly added field

• Changed addNewField() return type from void to Optional<FieldViewModel>
• Updated field validation error message to match entry type validation message
• Modified duplicate field detection to use case-insensitive comparison with equalsIgnoreCase()
• Return empty Optional when duplicate field detected, otherwise return the newly created field

jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/CustomEntryTypesTabViewModel.java


3. jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/FieldViewModel.java 🐞 Bug fix +1/-1

Normalize field name casing to lowercase

• Convert field name to lowercase before parsing to ensure consistent casing

jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/FieldViewModel.java


View more (5)
4. jablib/src/main/java/org/jabref/model/entry/field/FieldTextMapper.java ✨ Enhancement +1/-1

Capitalize first letter of custom field display names

• Apply capitalizeFirst() to all unknown field names in display name generation

jablib/src/main/java/org/jabref/model/entry/field/FieldTextMapper.java


5. jablib/src/test/java/org/jabref/logic/quality/consistency/BibliographyConsistencyCheckResultCsvWriterTest.java 🧪 Tests +1/-1

Update test for capitalized field names

• Updated test expectation to reflect capitalized custom field name

jablib/src/test/java/org/jabref/logic/quality/consistency/BibliographyConsistencyCheckResultCsvWriterTest.java


6. jablib/src/test/java/org/jabref/logic/quality/consistency/BibliographyConsistencyCheckResultTxtWriterTest.java 🧪 Tests +2/-2

Update tests for capitalized field names

• Updated two test expectations to reflect capitalized custom field name in output

jablib/src/test/java/org/jabref/logic/quality/consistency/BibliographyConsistencyCheckResultTxtWriterTest.java


7. CHANGELOG.md 📝 Documentation +2/-0

Document field validation fixes

• Added two entries documenting fixes for duplicate field creation and empty/space-containing fields

CHANGELOG.md


8. jablib/src/main/resources/l10n/JabRef_en.properties 📝 Documentation +1/-1

Update field validation error message

• Updated field validation error message to include "must not contain spaces" clause

jablib/src/main/resources/l10n/JabRef_en.properties


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Feb 19, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Remediation recommended

✅ 1. toLowerCase() missing Locale.ROOT 📘 Rule violation ✓ Correctness
Description
FieldViewModel.toField uses String.toLowerCase() without specifying Locale.ROOT, which can
produce incorrect field names under certain default locales (e.g., Turkish locale casing rules).
This is inconsistent with JabRef code quality conventions and can cause non-deterministic behavior
across environments.
Code

jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/FieldViewModel.java[63]

+        Field field = FieldFactory.parseField(type, displayName.getValue().toLowerCase());
Evidence
PR Compliance ID 6 requires adherence to JabRef style/quality guidance; using default-locale case
conversion is a known Java pitfall and can lead to incorrect results depending on user/system
locale. The changed line introduces default-locale lowercasing in toField.

AGENTS.md
jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/FieldViewModel.java[60-66]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`FieldViewModel.toField` lowercases `displayName` using `toLowerCase()` without an explicit locale, which can yield incorrect results under some system locales.
## Issue Context
JabRef generally uses locale-stable casing conversions (e.g., `Locale.ROOT`) for deterministic behavior across environments.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/FieldViewModel.java[60-66]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 2. Global title-casing blast radius 🐞 Bug ✓ Correctness
Description
FieldTextMapper.getDisplayName now applies StringUtil.capitalizeFirst broadly, which changes
user-visible labels and export/report headers across the app (not just the custom-entry-type UI) and
also forces the remainder of the name to lowercase (potentially mangling acronyms/camelCase for
non-standard fields).
Code

jablib/src/main/java/org/jabref/model/entry/field/FieldTextMapper.java[R36-40]

          return "Citationkey";
      }
-        return field.getName();
+        return StringUtil.capitalizeFirst(field.getName());
  }
Evidence
The PR changes FieldTextMapper to call StringUtil.capitalizeFirst(...) for most fields.
capitalizeFirst uppercases the first character and lowercases the rest, which is a behavior change
for any consumer of FieldTextMapper. FieldTextMapper is used widely in UI and export/report code, so
this change affects many surfaces beyond the custom entry type editor.

jablib/src/main/java/org/jabref/model/entry/field/FieldTextMapper.java[10-40]
jablib/src/main/java/org/jabref/logic/util/strings/StringUtil.java[658-666]
jabgui/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java[14-20]
jablib/src/main/java/org/jabref/logic/exporter/OOCalcDatabase.java[144-155]
jablib/src/main/java/org/jabref/logic/quality/consistency/BibliographyConsistencyCheckResultWriter.java[83-89]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`FieldTextMapper.getDisplayName` now title-cases field names via `StringUtil.capitalizeFirst`, which also lowercases the remainder of the string. Because `FieldTextMapper` is used across the UI and exports/reports, this is a broad user-visible behavior change (and may mangle acronyms/camelCase for unknown/internal fields).
### Issue Context
The PR description focuses on preventing empty/duplicate custom fields and capitalizing the first letter for each new field. Applying `capitalizeFirst` in `FieldTextMapper` impacts many unrelated components.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/model/entry/field/FieldTextMapper.java[10-40]
- jablib/src/main/java/org/jabref/logic/util/strings/StringUtil.java[658-666]
- jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/CustomEntryTypesTabViewModel.java[155-177]
- jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/FieldViewModel.java[26-34]
### Possible fixes
- Option A (scoped): Revert global change in `FieldTextMapper`, and instead capitalize only when adding custom fields in `CustomEntryTypesTabViewModel` / `FieldViewModel` (e.g., transform the user input or the `FieldViewModel.displayName`).
- Option B (preserve remainder): Introduce a helper that uppercases only the first character but leaves the rest unchanged, and use that for display names where appropriate.
- Option C (hybrid): Keep title-casing for standard fields only, but leave `UnknownField` display names as-is (or only uppercase first char without lowercasing rest) to avoid mangling user-defined casing.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@testlens-app

testlens-app Bot commented Feb 19, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 6d903ba
▶️ Tests: 11198 executed
⚪️ Checks: 63/63 completed


Learn more about TestLens at testlens.app.


assertEquals("""
entry type,citation key,custom,Pages,Title
entry type,citation key,Custom,Pages,Title

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these changes related and needed?

@pluto-han pluto-han Feb 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, now when a field is created, its first letter is capitalized like entry type. If dont change this code, tests will not pass

@Siedlerchr Siedlerchr Feb 20, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But fields should always be lowercase !

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But fields should always be lowercase !

Got it, i'll fix it now

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@koppor Just for clarification: Do we lowercase fields always?

@ThiloteE ThiloteE Feb 20, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for standardfields, customizable for custom fields: "Hardcode StandardField names and use exact or customized names otherwise". We have an ADR: https://devdocs.jabref.org/decisions/0049-hardcode-fieldnames.html#decision-outcome

@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Feb 20, 2026
@pluto-han

Copy link
Copy Markdown
Collaborator Author

I checked the error output but it seems not related to the part I modified.

@github-actions

Copy link
Copy Markdown
Contributor

Your pull request conflicts with the target branch.

Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line.

@github-actions github-actions Bot removed the status: changes-required Pull requests that are not yet complete label Feb 23, 2026
@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Feb 24, 2026
@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Feb 24, 2026
Comment thread CHANGELOG.md Outdated

@subhramit subhramit left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

@subhramit subhramit added the status: awaiting-second-review For non-trivial changes label Feb 24, 2026
@Siedlerchr Siedlerchr added this pull request to the merge queue Feb 24, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label Feb 24, 2026
Merged via the queue into JabRef:main with commit 503619e Feb 24, 2026
57 of 63 checks passed
Siedlerchr added a commit that referenced this pull request Feb 25, 2026
* refs/heads/main:
  Increase max assignments from 2 to 3
  Chore(deps): Bump io.zonky.test:embedded-postgres in /versions (#15213)
  Chore(deps): Bump jablib/src/main/resources/csl-styles (#15211)
  New Crowdin updates (#15208)
  Fix: Prevent creating empty or duplicate fields  (#15168)
  chore(deps): update jackson monorepo to v3.1.0 (#15203)
  Update KeywordEditor to work with escaping (#14929)
  Chore(deps): Bump com.dlsc.gemsfx:gemsfx in /versions (#15205)
  Chore(deps): Bump tools.jackson:jackson-bom in /versions (#15206)
  Fix: Reset External File Type to default (#15167)
  docs: fix link formatting in ADR 0012 (#15201)
RakockiW pushed a commit to RakockiW/jabref that referenced this pull request Mar 1, 2026
* Prevent empty fields

* Prevent duplicate fields

* add CHANGELOG.md

* scroll to newly added fields

* fix test fails

* fix test fails

* fix test fails

* fix test fails

* Apply suggestion from @subhramit

Co-authored-by: Subhramit Basu <subhramit.bb@live.in>

* custom fields should be lowercase

* explicit viewmodel name

* update CHANGELOG.md

* Apply suggestion from @subhramit

---------

Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
priyanshu16095 pushed a commit to priyanshu16095/jabref that referenced this pull request Mar 3, 2026
* Prevent empty fields

* Prevent duplicate fields

* add CHANGELOG.md

* scroll to newly added fields

* fix test fails

* fix test fails

* fix test fails

* fix test fails

* Apply suggestion from @subhramit

Co-authored-by: Subhramit Basu <subhramit.bb@live.in>

* custom fields should be lowercase

* explicit viewmodel name

* update CHANGELOG.md

* Apply suggestion from @subhramit

---------

Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: awaiting-second-review For non-trivial changes status: no-bot-comments status: to-be-merged PRs which are accepted and should go into the merge-queue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Entry Types Prefs: Make field duplicate prevention similar to entry type duplicate prevention

5 participants