fix(web): build a valid lquery for an exact ~ tree path - #181
Merged
murrayju merged 1 commit intoJul 31, 2026
Merged
Conversation
A memory at the ROOT of `~` (`me memory create --tree '~' foo`) made the UI
show "Failed to load: Internal error". Two bugs:
1. `exactTreeLquery` forced the server's tree-filter classifier down the
lquery branch by duplicating the last label as an alternation
(`work` -> `work|work`). For a top-level home node the path IS `~`, so it
emitted `~|~` — not parseable lquery, since `~` is home sugar the server
expands only as a LEADING segment and is not a legal ltree label. PG
rejected it with 42601. The synthetic root bucket (`.` -> `.|.`) was a
second latent case. Use the zero-label quantifier instead
(`~.*{0,0}`): it forces lquery detection AND pins the match to exactly
that path, while staying valid with `~` leading.
2. `mapSpaceError` mapped only 22023/22P02 to VALIDATION_ERROR. ltree's
lquery/ltxtquery parsers report a malformed pattern as 42601
(syntax_error), which fell through to a generic -32603 Internal error,
hiding the cause. A tree filter is caller-supplied, so 42601 now maps to
VALIDATION_ERROR.
Fixes TNT-248
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a web UI regression where expanding the ~ (home) tree node could send an invalid lquery (~|~), causing memory.search to fail and the UI to show “Internal error”. The PR updates the UI to generate a valid exact-match lquery for ~ and improves server-side error mapping so malformed ltree query patterns surface as validation errors.
Changes:
- Web:
exactTreeLquery()now pins exact matches by appending.*{0,0}(or*{0,0}for root), avoiding invalid alternation patterns for~and the synthetic root bucket. - Server: maps Postgres
42601(syntax_error) from malformedlquery/ltxtquerypatterns toVALIDATION_ERRORinstead of returning a generic internal error. - Tests: adds web unit tests for
exactTreeLquery()and new server integration tests covering exact~queries and malformed filters.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/web/src/api/queries.ts | Reworks exact-tree lquery generation to remain valid for ~ and root sentinel while preserving exact-match semantics. |
| packages/web/src/api/queries.test.ts | Adds unit coverage for exactTreeLquery() including ~ and root-sentinel regressions. |
| packages/server/rpc/memory/memory.ts | Maps 42601 SQLSTATE to VALIDATION_ERROR for caller-supplied malformed tree query filters. |
| packages/server/rpc/memory/memory.integration.test.ts | Adds integration coverage for exact ~-root filtering and validation errors on malformed tree filters. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+1
to
+3
| /** | ||
| * Unit tests for the pure query-param helpers (no network, no React). | ||
| */ |
jgpruitt
approved these changes
Jul 31, 2026
murrayju
deleted the
murrayju/tnt-248-internal-error-on-1-unnamed-memory-in
branch
July 31, 2026 20:26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes TNT-248.
Symptom
After putting a memory at the root of the home folder:
the UI's tree pane shows "Failed to load: Internal error". The failing request is the lazy exact-path fetch for the expanded
~node:Root cause
Two independent bugs.
1. The web UI built an invalid
lqueryfor~exactTreeLquery()(packages/web/src/api/queries.ts) forced the server's tree-filter classifier down thelquerybranch by duplicating the last label as an alternation:For a top-level home node the path is
~, so it produced~|~— the exact filter in the failing request. That isn't parseable lquery:~is home sugar, expanded server-side only as a leading segment, and it isn't a legal ltree label:The same trick also broke the synthetic root bucket (
.->.|.), a second latent case.Fix: append the zero-label quantifier instead of an alternation. It forces lquery detection and pins the match to exactly that path, and stays valid with
~leading:Verified against real PG:
home.x ~ home.x.*{0,0}is true,home.x.ais false — same exact-match semantics as before.2. The server reported a caller error as "Internal error"
mapSpaceError(packages/server/rpc/memory/memory.ts) mapped only22023/22P02toVALIDATION_ERROR. ltree's lquery/ltxtquery parsers report a malformed pattern as42601(syntax_error), which fell through to a generic-32603 Internal error, hiding the cause. A tree filter is caller-supplied, so42601now maps toVALIDATION_ERROR.Why it surfaced only now
It requires a memory at the root of
~. That's the only way the UI's tree node is the bare~withdirectCount > 0, which is what triggers the lazy exact-path fetch on auto-expansion.Tests
packages/web/src/api/queries.test.ts(new) —exactTreeLqueryunit tests: the~regression, the root sentinel, and an assertion that no alternation is ever emitted.packages/server/rpc/memory/memory.integration.test.ts— end-to-end against a real space schema: a memory at~root resolves via~.*{0,0}(and~.notes.*{0,0}one level down), and a malformed filter (~|~,share.a&&b) is aVALIDATION_ERRORrather than an internal error.Both new tests fail with the two source fixes reverted (confirmed by stashing only the source files), so they genuinely pin the bug.
./bun run check:fullis green: 1208 unit / 1588 db / 45 e2e, 0 fail.