Skip to content

DsoEditMetadataValueComponent#ngOnChanges fires vocabulary requests on incomplete metadata fields, spamming 422 errors in dspace.log #5109

Description

@MMilosz

Describe the bug

When editing an item metadata field in DSpace, if the user slowly types or pauses typing while the field name is incomplete (e.g., 'dc.contri'), this triggers a 422 Unprocessable Entity error in the backend, filling dspace.log with lengthy stack traces.

Slowly typing dc.contributor.author generated 3125 lines of logs.

Tested on the latest DSpace 10.0-SNAPSHOT.

Root cause: The DsoEditMetadataValueComponent triggers vocabulary requests via ngOnChanges without sufficient validation or debouncing, see the code:

/**
* The type of edit field that should be displayed
*/
fieldType$: Observable<EditMetadataValueFieldType>;

ngOnChanges(changes: SimpleChanges): void {
if (changes.mdField) {
this.fieldType$ = this.getFieldType();
}
}

/**
* Retrieves the {@link EditMetadataValueFieldType} to be displayed for the current field while in edit mode.
*/
getFieldType(): Observable<EditMetadataValueFieldType> {
return this.dsoEditMetadataFieldService.findDsoFieldVocabulary(this.dso, this.mdField).pipe(
map((vocabulary: Vocabulary) => {
if (hasValue(vocabulary)) {
return EditMetadataValueFieldType.AUTHORITY;
}
if (this.mdField === 'dspace.entity.type') {
return EditMetadataValueFieldType.ENTITY_TYPE;
}
return EditMetadataValueFieldType.PLAIN_TEXT;
}),
);
}

/**
* Find the vocabulary of the given {@link mdField} for the given item.
*
* @param dso The item
* @param mdField The metadata field
*/
findDsoFieldVocabulary(dso: DSpaceObject, mdField: string): Observable<Vocabulary> {
if (isNotEmpty(mdField)) {
const owningCollection$: Observable<Collection> = this.itemService.findByHref(dso._links.self.href, true, true, followLink('owningCollection')).pipe(
getFirstSucceededRemoteDataPayload(),
switchMap((item: Item) => item.owningCollection),
getFirstSucceededRemoteDataPayload(),
);
return owningCollection$.pipe(
switchMap((c: Collection) => this.vocabularyService.getVocabularyByMetadataAndCollection(mdField, c.uuid).pipe(
getFirstSucceededRemoteDataPayload(),
)),
);
} else {
return of(undefined);
}
}

Each keystroke in the metadata field input triggers two simultaneous requests:

  1. /server/api/submission/vocabularies/search/byMetadataAndCollection?metadata={METADATA_FIELD_NAME}&collection={UUID}
  2. /server/api/core/metadatafields/search/byFieldName?page=0&size=20&sort=fieldName,ASC&schema=&element=&qualifier=&query={METADATA_FIELD_NAME}&exactName=&embed=schema

To Reproduce

Requirement: access to backend logs.

  1. Navigate to an Item > Edit > Metadata tab
  2. Press the "+ Add" button
  3. In the metadata field name input, start slowly typing 'dc.contributor.author'.
  4. (Optionally: Pause typing for <1 second while the field name is still incomplete)
  5. Observe the backend logs - multiple 422 error entries appear

Below is the output of $ docker logs -f dspace | grep -B 1 "is not a valid" command

Click here to see log messages.

2026-02-13 01:17:16,687 ERROR unknown 10221764-0610-4be7-9f90-00661c82a8d9 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: d is not a valid metadata -- 2026-02-13 01:17:17,514 ERROR unknown db649d7f-5197-46e5-93e5-20341eb26b67 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc is not a valid metadata -- 2026-02-13 01:17:18,131 ERROR unknown 33a6f41c-247e-43d7-9b00-a22619501bfa org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc. is not a valid metadata -- 2026-02-13 01:17:18,732 ERROR unknown a31d51c5-ae85-4b67-9321-9cd57a6a6ff6 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.c is not a valid metadata -- 2026-02-13 01:17:19,225 ERROR unknown aed91490-c60c-4da1-8644-146b12db025d org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.co is not a valid metadata -- 2026-02-13 01:17:19,777 ERROR unknown 387600f8-1c0b-44db-b63d-a4c1169ddddd org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.con is not a valid metadata -- 2026-02-13 01:17:20,286 ERROR unknown 169a8b11-5a9f-481e-ad9d-903db7720f82 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.cont is not a valid metadata -- 2026-02-13 01:17:20,612 ERROR unknown c2f5460b-3a88-400e-9c31-6afce6d110c9 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.contr is not a valid metadata -- 2026-02-13 01:17:21,058 ERROR unknown 66ee72ff-9029-4f14-af01-8859a15cb788 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.contri is not a valid metadata -- 2026-02-13 01:17:21,691 ERROR unknown 04e35b3e-f914-47b9-b853-601f8dd1f098 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.contrib is not a valid metadata -- 2026-02-13 01:17:22,021 ERROR unknown 37f41c8a-7635-428b-a341-69bac40a3186 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.contribu is not a valid metadata -- 2026-02-13 01:17:22,403 ERROR unknown 89b02b66-45f0-46d3-9216-a5a874b3ea93 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.contribut is not a valid metadata -- 2026-02-13 01:17:22,740 ERROR unknown 1d796e61-c8ca-45ec-9443-a493588cb272 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.contributo is not a valid metadata -- 2026-02-13 01:17:23,800 ERROR unknown 406aa231-3a27-4119-8250-2c2d40f4a9e8 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.contributor.a is not a valid metadata -- 2026-02-13 01:17:24,886 ERROR unknown b61b6f0c-777d-4fc6-b75a-1ee3ce55c325 org.dspace.app.rest.exception.DSpaceApiExceptionControllerAdvice @ Unprocessable or invalid entity (status:422) org.dspace.app.rest.exception.UnprocessableEntityException: dc.contributor.autho is not a valid metadata

Expected behavior

  1. The frontend should debounce validation/vocabulary lookup requests until the user has stopped typing
  2. The frontend should only make API calls when the metadata field name matches a valid format (bare minimum: schema + element; pattern like char + . + char
  3. No unusual backend errors should be triggered during normal typing interactions
  4. The dspace.log should not be polluted with stack traces from incomplete user input

Potential solutions:

  • Implement debouncing + validation
  • Anything else?

Related work

Not found

Metadata

Metadata

Labels

affects: 10.xIssue impacts 10.x releasesaffects: 9.xIssue impacts 9.x releasesaffects: mainIssue impacts "main" (latest release).bugcomponent: Item(Archived) Item display or editing

Type

Fields

No fields configured for Bug.

Projects

Status
🏗 In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions