Skip to content

[Feat]: Limit characters allowed in field/property names; reserve field/property names beginning with underscore #1383

Description

@edwinyyyu

Is your feature request related to a problem?

There are complaints about in-database representations being unreadable #633 . It makes debugging and auditing harder.

Many databases or storage solutions do not support arbitrary-length field or property names.

What may work on one backend one day may stop working on the next.

Describe the solution you'd like

The current approach (as in Neo4j) is to sanitize the names. This involves a lot of extra prefixing or bijective encoding and decoding steps that turns a simple field or property name into a long mess. It also results in incompatible data depending on how deeply wrapped the systems are.

Preferred

  • Only allow [a-z0-9_]+ (lowercase alphanumeric and underscores).
  • Limit field/property names to 32 characters.
    • AWS and some others support only up to 63 chars
    • Chroma supports only up to 36 chars
  • Reserve underscore-prefixed names for system.

This will allow for easily readable and filterable metadata, compatible with (nearly?) all storage backends. No unbounded growth of metadata keys. At most one translation layer between database and source (like replacing underscores with hyphens; or the DB itself reserves underscore prefix, in which case we'd add a simple prefix).

Filters

All system-defined metadata (external/query-facing --> generic internal):

  • timestamp --> _timestamp
  • custom_system_key --> _custom_system_key
  • m.custom_user_key --> custom_user_key

Describe alternatives you've considered

Each database supports different name limitations.

  • Makes migration more difficult.
  • Harder to compose different components without shared understanding of limitations.

Additional context

No response

Activity

  1. alighazi288 commented on May 5, 2026

    @alighazi288
    Contributor

    Hey @edwinyyyu, happy to take this. Plan: introduce SafeFieldName = Annotated[str, AfterValidator(_is_valid_field_name)] in common/api/spec.py (rules: starts with a-z, followed by [a-z0-9_]*, ≤32 chars) and apply it via Pydantic AfterValidator exclusively to input surfaces (MemoryMessage.metadata, *Spec.set_metadata, AddFeatureSpec.{tag,feature,category_name}, UpdateFeatureSpec.{tag,feature,category_name,metadata}, CreateSemanticSetTypeSpec.metadata_tags).

    To avoid breaking reads of legacy records, response/entity models stay permissive, existing rows still deserialize, but new writes are forced to conform. Two architectural calls I want to flag:

    1. set_id remains permissive (Out of scope). I initially considered tightening set_id to stop the dirty FeatureSet_<sanitized_set_id> Neo4j labels mentioned in [Bug][v2]: Neo4j node labels #633. However, set_id is used referentially; if we tighten it on AddFeatureSpec or UpdateFeatureSpec, users won't be able to add features to or update existing legacy sets that have non-conforming IDs. Fully resolving [Bug][v2]: Neo4j node labels #633 requires rethinking the identifier model, which belongs in a separate issue. The _sanitize_identifier translation layer will stay as a defensive backstop for now.

    2. Filter-expression key validation is out of scope. SearchMemoriesSpec.filter is a free-form string referencing metadata keys and tightening those references needs a parser change which I believe belongs in a separate issue.
      Push back if either call is wrong, otherwise I'll start working on the PR.

  2. github-actions commented on Aug 3, 2026

    @github-actions
    Contributor

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. If this issue is still relevant, please comment to keep it open, or add the keep-open label if it should remain open indefinitely (e.g., a roadmap item awaiting a champion). Thank you for your contributions.

  3. added
    keep-openPrevents the auto-close task from closing this issue.
    on Aug 3, 2026
  4. edwinyyyu commented on Sep 2, 2026

    @edwinyyyu
    ContributorAuthor

    Internally changing to use UUID would be better. Externally can allow a wider set.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Stalekeep-openPrevents the auto-close task from closing this issue.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions