Skip to content

[Bug]: React error on Memory web page when an object is returned for the category #2665

@bfocht

Description

@bfocht

Summary

Broken UX due to invalid category

Affected component

runtime/daemon

Severity

S2 - degraded behavior

Current behavior

The memory API returns category as {"custom": "travel"} for custom categories,
but the React frontend expects a plain string. This causes [object Object]
rendering errors on the Memory page.
The root cause is in Rust's serde: #[serde(rename_all = "snake_case")] with the default externally-tagged enum
representation serializes unit variants as strings ("core", "daily") but wraps
data-carrying variants in objects ({"custom": "travel"}).

Fix: Custom serde for MemoryCategory

File: src/memory/traits.rs

Replace the derived Serialize/Deserialize on MemoryCategory with custom
implementations that always serialize/deserialize as a plain string — matching
the existing Display impl and category_to_str/str_to_category pattern in
sqlite.rs.

  1. Remove Serialize, Deserialize from the derive macro on MemoryCategory
  2. Remove #[serde(rename_all = "snake_case")]
  3. Add manual Serialize impl: serialize as the string form ("core", "daily",
    "conversation", or the custom name)
  4. Add manual Deserialize impl: deserialize a string, mapping known names to
    their variants and everything else to Custom(s)
  5. Update the existing serde test (memory_category_serde_uses_snake_case) to
    also cover Custom("travel") → "travel" round-trip

No frontend changes needed — the TS type category: string is already correct;
it's the backend that's violating the contract.

Verification

cargo test -p zeroclaw -- memory_category_serde
cargo clippy --all-targets -- -D warnings

Then hit GET /api/memory and confirm custom categories return as plain
strings.

Expected behavior

Page will Render correctly the TS type category: string is already correct

Steps to reproduce

    #[test]
    fn memory_category_serde_uses_snake_case() {
        // Serialization: all variants produce plain strings
        let core = serde_json::to_string(&MemoryCategory::Core).unwrap();
        let daily = serde_json::to_string(&MemoryCategory::Daily).unwrap();
        let conversation = serde_json::to_string(&MemoryCategory::Conversation).unwrap();
        let custom = serde_json::to_string(&MemoryCategory::Custom("travel".into())).unwrap();

        assert_eq!(core, "\"core\"");
        assert_eq!(daily, "\"daily\"");
        assert_eq!(conversation, "\"conversation\"");
        assert_eq!(custom, "\"travel\"");

        // Deserialization: round-trip for all variants
        assert_eq!(
            serde_json::from_str::<MemoryCategory>("\"core\"").unwrap(),
            MemoryCategory::Core
        );
        assert_eq!(
            serde_json::from_str::<MemoryCategory>("\"daily\"").unwrap(),
            MemoryCategory::Daily
        );
        assert_eq!(
            serde_json::from_str::<MemoryCategory>("\"conversation\"").unwrap(),
            MemoryCategory::Conversation
        );
        assert_eq!(
            serde_json::from_str::<MemoryCategory>("\"travel\"").unwrap(),
            MemoryCategory::Custom("travel".into())
        );
    }

Impact

Broken Memory Page

Logs / stack traces


ZeroClaw version

f2ba33f

Rust version

1.93.1

Operating system

Unbuntu

Regression?

Unknown

Pre-flight checks

  • I reproduced this on the latest main branch or latest release.
  • I redacted secrets/tokens from logs.
  • I removed personal identifiers and replaced identity-specific data with neutral placeholders.

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions