Skip to content

Python recall() validates neither its query nor max_distance: empty query is signed and sent (mock raises), and a NaN/negative max_distance silently returns zero results (real client and mock) #1248

Closed

Description

@DerezN

Surface

Python SDK (memwal)

Network

Mainnet (relayer.memory.walrus.xyz)

Package version

dev HEAD d88005a

What happened?

Walrus Session 9 — Best Bug Reports submission. Verified 2026-10-19 against
a fresh clone of upstream dev (HEAD d88005ae), Python 3.12, httpx +
pynacl, stub relayer. This is the Python remainder of two accepted
TypeScript reports — #1215 (empty recall query, fixed by #1228) and #1212
(NaN/negative maxDistance silently zeroing results, fixed by #1227). Both
fixes touched only the TypeScript SDK; the Python client still has neither
guard, although the Python mock proves the contract is expected there too.

Severity: Low–Medium — a silent empty result set that is
indistinguishable from an empty namespace, plus a signed request carrying an
empty query the SDK's own mock rejects.

  1. Empty query. MemWal.recall("") performs no validation
    (packages/python-sdk-memwal/memwal/client.py, recall()): the signed
    body is {"query":"","limit":10,"namespace":"default"}.
    MemWalMock.recall("") raises ValueError: query cannot be empty for
    the identical call — the mock defines a contract the real client ignores,
    the same divergence MemWal.recall() sends empty query and NaN/negative limit (and NaN scoring weights) to the relayer unvalidated — the mock rejects them; wire-verified through a live SEAL session #1215 reported for TypeScript.
  2. NaN / negative max_distance. The client-side filter is
    [m for m in memories if m.distance < max_distance]. Every comparison
    against NaN is False, and every real distance is ≥ 0, so
    max_distance=float("nan") and max_distance=-1 both drop every hit
    the server returned. Verified with the stub returning two hits
    (distances 0.5, 1.0, total=2): both calls resolve with
    results=[], total=2. MemWalMock.recall has the identical unguarded
    filter and the identical silent-zero behavior. (For TypeScript, fix(sdk): reject a non-finite recall maxDistance #1227
    fixed real client and mock together; neither Python implementation was
    touched.)

Suggested fix: _reject_blank_text/mock-style validation for query
in recall(); math.isfinite(max_distance) and max_distance >= 0 guard
before the filter, in client.py and mock.py.

Also submitted via the official Walrus Session 9 bug-feedback form.

Steps to reproduce

(full script accompanies this report):

client = MemWal.create(key=KEY, account_id=ACCOUNT, server_url=stub_url)
await client.recall("")                                  # resolves; wire: {"query":"",...}
await client.recall("coffee", max_distance=float("nan")) # RecallResult(results=[], total=2)
await client.recall("coffee", max_distance=-1.0)         # RecallResult(results=[], total=2)

mock = MemWalMock.create()
await mock.recall("")                                    # ValueError: query cannot be empty
await mock.recall("coffee", max_distance=float("nan"))   # results=[] — silent, like the real client

Expected

the Python client rejects a blank query (as its mock already
does) and rejects a non-finite or negative max_distance with a
ValueError, mirroring the TypeScript errors from #1227/#1228 — in both
the real client and the mock.

Actual

the empty query is signed and sent; the NaN/negative cutoffsilently discards every hit.

Logs or error text

Checks

  • I searched existing issues and this is not a duplicate.
  • This report contains no private keys, mnemonics, or other secrets.

Activity

  1. github-actions commented on Oct 19, 2026

    @github-actions

    Thank you for opening this issue, a team member will review it shortly.

  2. added 6 commits that reference this issue on Oct 23, 2026
    669a9ea
    d51bb7e
    2019e51
    cf6cc09
    d5ac212
    686e69a
  3. harrymove-ctrl commented on Oct 27, 2026

    @harrymove-ctrl
    Collaborator

    Thanks for flagging this. We reproduced it, and the fix is merged in #1254 and will be included in memwal 0.2.2. Please reopen if you still see it after upgrading.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions