Bug Description
After PR #766 added AliasChoices to MCP tool parameters, write_note returns the
"note already exists" error even when called with an explicit overwrite=true. The
parameter appears to be dropped before reaching the function body. The only call-site
workaround I've found is delete_note followed by write_note without overwrite.
Steps To Reproduce
From an MCP client (Claude Code, in my case):
-
Create a note:
write_note(title="overwrite-repro", content="v1", directory="test")
-
Attempt to overwrite the same path:
write_note(title="overwrite-repro", content="v2", directory="test", overwrite=true)
Expected Behavior
The note at test/overwrite-repro is replaced with v2.
Actual Behavior
The call returns the standard "already exists" guidance message, which itself suggests
overwrite=True as the fix:
# Error: Note already exists
**"overwrite-repro"** already exists (permalink: `test/overwrite-repro`).
`write_note` does not overwrite by default. Choose an option:
| Goal | Action |
|------|--------|
| ... |
| Full replace | write_note("overwrite-repro", ..., overwrite=True) |
The note on disk is unchanged. delete_note("test/overwrite-repro") followed by a fresh
write_note(...) (no overwrite argument) succeeds.
Environment
- OS: Windows 11 Pro 10.0.26200
- Python: 3.13 (via uv)
- Basic Memory: 0.20.3
- Installation:
uv tool
- MCP client: Claude Code
Additional Context
The overwrite parameter on write_note was changed in commit ee1558ea (PR #766,
"accept training-data-friendly parameter aliases") from:
overwrite: bool | None = None,
to:
overwrite: Annotated[
bool | None,
Field(default=None, validation_alias=AliasChoices("overwrite", "force", "replace")),
] = None,
The function-body check looks correct on a static read:
effective_overwrite = overwrite if overwrite is not None else ConfigManager().config.write_note_overwrite_default
# ...
if not effective_overwrite:
# raises the "already exists" path
So True would pass this gate if it arrived. The error path firing means overwrite is
arriving as None (or as the config default False) at the function body — i.e. the
explicit true from the MCP client isn't surviving FastMCP's argument extraction. I
haven't traced FastMCP's handling of Field(validation_alias=...) on a function
parameter (vs a Pydantic model field), so I can't say whether the regression is in
FastMCP, in how this annotation is interpreted, or something else. The directory
parameter received the same AliasChoices treatment in the same commit and works for
me, so if it's an alias-resolution issue it may be specific to bool | None typed
parameters.
Two workarounds that do work:
- Set
BASIC_MEMORY_WRITE_NOTE_OVERWRITE_DEFAULT=true (or
write_note_overwrite_default: true in config) — flips the None-branch default so
dropped overwrite values behave as overwrite=true.
- At the call site,
delete_note first, then write_note without an overwrite
argument.
Possible Solution
I haven't tested a patch. Happy to test on Windows + Claude Code if a hypothesis or fix
is worth verifying.
Bug Description
After PR #766 added
AliasChoicesto MCP tool parameters,write_notereturns the"note already exists" error even when called with an explicit
overwrite=true. Theparameter appears to be dropped before reaching the function body. The only call-site
workaround I've found is
delete_notefollowed bywrite_notewithoutoverwrite.Steps To Reproduce
From an MCP client (Claude Code, in my case):
Create a note:
Attempt to overwrite the same path:
Expected Behavior
The note at
test/overwrite-reprois replaced withv2.Actual Behavior
The call returns the standard "already exists" guidance message, which itself suggests
overwrite=Trueas the fix:The note on disk is unchanged.
delete_note("test/overwrite-repro")followed by a freshwrite_note(...)(no overwrite argument) succeeds.Environment
uv toolAdditional Context
The
overwriteparameter onwrite_notewas changed in commitee1558ea(PR #766,"accept training-data-friendly parameter aliases") from:
to:
The function-body check looks correct on a static read:
So
Truewould pass this gate if it arrived. The error path firing meansoverwriteisarriving as
None(or as the config defaultFalse) at the function body — i.e. theexplicit
truefrom the MCP client isn't surviving FastMCP's argument extraction. Ihaven't traced FastMCP's handling of
Field(validation_alias=...)on a functionparameter (vs a Pydantic model field), so I can't say whether the regression is in
FastMCP, in how this annotation is interpreted, or something else. The
directoryparameter received the same
AliasChoicestreatment in the same commit and works forme, so if it's an alias-resolution issue it may be specific to
bool | Nonetypedparameters.
Two workarounds that do work:
BASIC_MEMORY_WRITE_NOTE_OVERWRITE_DEFAULT=true(orwrite_note_overwrite_default: truein config) — flips theNone-branch default sodropped
overwritevalues behave as overwrite=true.delete_notefirst, thenwrite_notewithout anoverwriteargument.
Possible Solution
I haven't tested a patch. Happy to test on Windows + Claude Code if a hypothesis or fix
is worth verifying.