Skip to content

[BUG] write_note lowercases note_type while type matching stays case-sensitive, splitting one logical type into two populations #1180

Description

@cabras-co

Bug Description

write_note(note_type="Task") stores type: task (lowercased) in the note's frontmatter, but type matching in schema_validate and search_notes (note_types=[...]) is case-sensitive. Notes whose frontmatter says type: Task (hand-written or migrated) and notes created through write_note end up as two separate populations that no single query covers, so type-wide validation silently reports only partial results.

Steps To Reproduce

  1. Install Basic Memory 0.22.1 and set up a local project.
  2. Create a schema note for entity Task (schema/Task.md).
  3. Create note A by hand with frontmatter type: Task.
  4. Create note B via the MCP tool write_note(title=..., note_type="Task", ...): its stored frontmatter reads type: task.
  5. Run schema_validate(note_type="Task"), then schema_validate(note_type="task").

Expected Behavior

One logical type is one population: either write_note preserves the capitalization it was given, or type matching is case-insensitive across schema_validate / search_notes / metadata filters. Either way, a single call validates all notes of the type.

Actual Behavior

schema_validate(note_type="Task") validates only note A; schema_validate(note_type="task") validates only note B. Neither call reports the other population, and there is no warning that a differently-capitalized sibling type exists.

Environment

  • OS: Windows 11 Home (10.0.26200)
  • Python version: 3.14.6
  • Basic Memory version: 0.22.1
  • Installation method: uv tool
  • Claude Desktop version: n/a (MCP tools called from Claude Code CLI)

Additional Context

Hit on 2026-08-03 while batch-migrating 25 task notes into a project that already had 8 hand-migrated notes with type: Task: validating "all tasks" required two separate calls with different capitalizations, and it is easy to believe everything was validated when only half was visible.

Possible Solution

Normalize type on write AND compare case-insensitively on read, or preserve the given capitalization end to end. Consistency in either direction fixes the split; the current mix (normalize on write, exact-match on read) is what creates the two populations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions