Skip to content

Raise max_field_value_size (5,120 B) for non-indexed document properties #5268

Description

@PastaPastaPasta

Every string or byte value in a document is capped at 5,120 bytes (max_field_value_size), including properties that no index uses. Ordinary long text, like a pull request description or release notes, often goes over that, even though the whole transition may be 20,480 bytes. We'd like non-indexed properties to be allowed to go up to what fits in a transition, still bounded by the schema and billed per byte.

We hit this building Dash Forge, a git forge that runs on Platform.

Expected Behavior

A non-indexed string or byte-array property can hold a value as large as its schema allows (maxLength / maxBytes / maxItems), up to a new, larger system limit (for example 16 KiB), as long as the whole state transition still fits max_state_transition_size. Storage and processing are billed per byte, as they are today.

Current Behavior

Impact on applications. We sampled GitHub on 2026-10-04 (pull request bodies, UTF-8 bytes, newest first):

Repository Sample Bodies over 5,120 B Largest Over 16 KiB
dashpay/dash 500 most recent PRs (#7261–#7801) 80 (16 %) 36,231 B 4
dashpay/platform 100 most recent PRs (#5136–#5262) 56 (56 %) 25,420 B 6

So a forge, a forum, a docs app, or anything that stores user-written text runs into this regularly. A limit around 16 KiB would cover most of these bodies, though not all of them.

Our workaround. When a text is longer than its field, we store the full text as a separate content-addressed artifact, split across several chunk documents, plus a manifest. The field keeps the first part of the text and a trailer that names the artifact (forge-v2.md §6.3). This costs extra writes and fees for the author, and extra requests for every reader. Because our contract only lets maintainers write artifacts, other users still can't post a long text. Before this, our importer cut the text and linked to the original on GitHub, which ties the content to a host we don't control.

Possible Solution

A suggestion:

  • Keep 5,120 B (or the current rules) for values that are indexed or that become a GroveDB key.
  • Add a separate, larger limit for non-indexed string and byte-array properties, for example 16,384 B. The real bound is still max_state_transition_size, and the schema's own maxLength / maxBytes / maxItems keep fee estimation bounded as it is now.
  • The entryPayload check of indexOnly types reuses max_field_value_size as its cap (try_from_schema/common/mod.rs#L3800-L3806), so it would probably keep the current value under its own name.
  • New protocol version only. Existing contracts and documents are unchanged, and a contract can use the larger size by adding a new optional property in an update.

We may be missing a reason the per-value cap must stay at 5,120 B for non-indexed data (storage layout, proof size, fee estimation). If there is one, it would help to have it documented next to the limit.

Alternatives Considered

  • Splitting text into a typed array of strings. From protocol version 14 the 5,120-byte limit applies to each element, not to the list (typed-arrays.md#L63). That works, but every writer and reader has to split and rejoin the text at UTF-8 boundaries, and maxBytes / propertyConstraints can't treat it as one text.
  • Several fixed fields (body1, body2, ...). The same problem, and it uses up schema properties.
  • A separate artifact (our current workaround). It costs more, needs more requests and needs permission to write artifacts.
  • Storing it off Platform. That gives up the proofs.

Additional Context

  • Platform 5.0.0-beta.1 (protocol version 14) on a devnet (sakura).
  • SDKs: @dashevo/evo-sdk and @dashevo/wasm-sdk 5.0.0-beta.1, and rs dash-sdk / dpp at tag v5.0.0-beta.1.
  • Sample method: GET /repos/{owner}/{repo}/pulls?state=all&sort=created&direction=desc, measuring the UTF-8 byte length of body.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions