Problem/Motivation

When a string field (mapped to a keyword field in OpenSearch) contains a value exceeding 32,766 bytes, OpenSearch throws a max_bytes_length_exceeded_exception and the request fails with a 400 status code:

  [error] Document contains at least one immense term in field="processed" (whose UTF8 encoding is longer than the max length 32766), all of which were skipped. Please correct the analyzer to not produce such terms. The prefix of the first immense term is: '...[redacted]...', original message: bytes can be at most 32766 in length; got 37582 max_bytes_length_exceeded_exception: bytes can be at most 32766 in length; got 37582 for id: entity:my_entity/123:und. Status code: 400

This limit is IndexWriter.MAX_TERM_LENGTH, a hard limit enforced by Lucene's engine. It applies to keyword fields because their values are indexed as a single term. Fulltext (text) fields are not affected since their content is tokenized into individual words.

In most cases this error indicates a field type misconfiguration: a field containing long text content is indexed as string (keyword) when it should be fulltext (text). However, regardless of root cause, the current behavior (a hard 400 error that aborts the rest of the bulk indexing request) is disruptive. The module could handle this gracefully by truncating the oversized value and logging a warning that guides the site administrator toward the correct fix.

Steps to reproduce

  1. Configure a Search API index with a field of type string.
  2. Index an entity where that field contains a value longer than 32,766 bytes.
  3. Observe a 400 error and indexing failure in the logs.

Proposed resolution

In IndexParamBuilder::buildFieldValues(), truncate string type values to MAX_TERM_BYTES (32,766) using mb_strcut() before indexing, to respect UTF-8 multibyte character boundaries. Log a warning when truncation occurs so site admins are informed and can correct the underlying field type configuration.

Note: TextValue instances (fulltext fields) do not need truncation since their content is tokenized by OpenSearch's analyzer.

Remaining tasks

  • Submit initial PR.

User interface changes

None.

API changes

None.

Data model changes

None.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

arlina created an issue. See original summary.

arlina’s picture

Status: Active » Needs review

Submitted a MR, changing status to "needs review".

kim.pepper’s picture

Status: Needs review » Needs work

Thanks for your MR. This looks great.

I went to run a test-only pipeline to ensure the test fails currently in HEAD, and it got an error instead about an undefined constant IndexParamBuilder::MAX_TERM_BYTES. Could we just define a test only variable / const?

arlina’s picture

Status: Needs work » Needs review

PR feedback resolved, changing back to needs review.

  • kim.pepper committed b3040eee on 2.x authored by arlina
    fix: #3576613 Indexing fails with max_bytes_length_exceeded_exception...
kim.pepper’s picture

Status: Needs review » Fixed

Committed to 2.x and cherry-picked to 3.x. Thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • kim.pepper committed d481505d on 3.x
    fix: #3576613 Indexing fails with max_bytes_length_exceeded_exception...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.