Summary
Reading a content-collection file at a nested path (a file inside a sub-"folder") fails on the read/Get path because the collection boundary is resolved incorrectly: the first path segment after the collection root is consumed as a collection name instead of being treated as part of the relative key within the collection. Flat paths (content/{file}) resolve fine; any nested path (content/{sub}/{file}) fails.
This is not the URL-decode bug fixed in #326 / #364 — it reproduces with a pure-ASCII, space-free path, so no percent-encoding is involved. #364 explicitly noted its fix was "not related to nesting depth"; this is that separate, nesting-related defect, on a different code path (the kernel/agent read, not the portal browsing/serving route).
Steps to reproduce
Two reads of nonexistent paths in the default content collection are enough to expose the resolver's branch — no files need to exist:
- Read
{node}/content/nope.pdf (flat, nonexistent)
→ File 'nope.pdf' not found in collection 'content'
The collection resolves correctly to content; only the file lookup fails. Correct.
- Read
{node}/content/subdir/nope.pdf (nested, pure ASCII, nonexistent)
→ Content collection 'subdir' not found
The resolver consumes subdir as a collection name; it never treats subdir/nope.pdf as a relative key inside content. Wrong.
With a real nested file present, the same failure blocks reads: a file at, e.g., content/reports/2024/summary.pdf cannot be read, failing with Content collection 'reports' not found — while the exact same file lists correctly in the browser and is fully indexed/searchable.
Actual vs. expected
- Actual: for
content/{sub}/…/{file} the resolver splits the collection boundary after the wrong segment and reports Content collection '{sub}' not found.
- Expected: the collection is
content (as in the flat case) and {sub}/…/{file} is the relative key handed to the provider — i.e. the file resolves, or fails as a plain file-not-found within content, exactly as flat paths do.
The two failures use different error templates — "File … not found in collection 'content'" (flat) vs. "Content collection '{sub}' not found" (nested) — confirming two different code branches.
Why this is distinct from #326 / #364
Import-vs-read asymmetry (diagnostic hook)
A nested file that the read path cannot resolve is nonetheless indexed successfully at import — chunks and a summary are produced from the same nested blob key. So the import/index path resolves nested keys correctly while the on-demand read path does not. The fix should align the read-path resolution with whatever the indexer already does.
Impact
Any content-collection file stored under a sub-"folder" is unreadable via Get / IContentService after upload, even though it lists in the file browser and indexes/searches fine. AI agents that read uploaded documents by path therefore cannot process files in nested folders at all — only files at the flat collection root are reachable.
Suggested area
src/MeshWeaver.ContentCollections/ — the path → (collection, relative-key) resolution used by the read path, which is distinct from the browsing/serving route code (CollectionNamedLayoutArea, ContentLayoutArea) fixed in #326 / #364. The resolver should treat the registered collection root (e.g. {node}/content) as the boundary and pass the entire remainder as the provider's relative key, rather than consuming the next segment as a collection name. A regression test reading a nested pure-ASCII path (content/sub/file.txt) through the read path would pin it.
Related
Summary
Reading a content-collection file at a nested path (a file inside a sub-"folder") fails on the read/
Getpath because the collection boundary is resolved incorrectly: the first path segment after the collection root is consumed as a collection name instead of being treated as part of the relative key within the collection. Flat paths (content/{file}) resolve fine; any nested path (content/{sub}/{file}) fails.This is not the URL-decode bug fixed in #326 / #364 — it reproduces with a pure-ASCII, space-free path, so no percent-encoding is involved. #364 explicitly noted its fix was "not related to nesting depth"; this is that separate, nesting-related defect, on a different code path (the kernel/agent read, not the portal browsing/serving route).
Steps to reproduce
Two reads of nonexistent paths in the default
contentcollection are enough to expose the resolver's branch — no files need to exist:{node}/content/nope.pdf(flat, nonexistent)→
File 'nope.pdf' not found in collection 'content'The collection resolves correctly to
content; only the file lookup fails. Correct.{node}/content/subdir/nope.pdf(nested, pure ASCII, nonexistent)→
Content collection 'subdir' not foundThe resolver consumes
subdiras a collection name; it never treatssubdir/nope.pdfas a relative key insidecontent. Wrong.With a real nested file present, the same failure blocks reads: a file at, e.g.,
content/reports/2024/summary.pdfcannot be read, failing withContent collection 'reports' not found— while the exact same file lists correctly in the browser and is fully indexed/searchable.Actual vs. expected
content/{sub}/…/{file}the resolver splits the collection boundary after the wrong segment and reportsContent collection '{sub}' not found.content(as in the flat case) and{sub}/…/{file}is the relative key handed to the provider — i.e. the file resolves, or fails as a plain file-not-found withincontent, exactly as flat paths do.The two failures use different error templates — "File … not found in collection 'content'" (flat) vs. "Content collection '{sub}' not found" (nested) — confirming two different code branches.
Why this is distinct from #326 / #364
content, and only the file name matched the encoded form. Content collection route does not URL-decode path segments — files/folders with spaces (or other encoded characters) return "not found" #364 states the fix is "not related to nesting depth," and Content-collection file serving fails for paths with spaces — lookup uses the URL-encoded path #326 confirms the kernel read (ContentCollection.GetContentAsyncviaIContentService) succeeds with a decoded path.Get/IContentService. Because the trigger is a pure-ASCII path, the URL-decode fixes neither cause nor repair it.Import-vs-read asymmetry (diagnostic hook)
A nested file that the read path cannot resolve is nonetheless indexed successfully at import — chunks and a summary are produced from the same nested blob key. So the import/index path resolves nested keys correctly while the on-demand read path does not. The fix should align the read-path resolution with whatever the indexer already does.
Impact
Any content-collection file stored under a sub-"folder" is unreadable via
Get/IContentServiceafter upload, even though it lists in the file browser and indexes/searches fine. AI agents that read uploaded documents by path therefore cannot process files in nested folders at all — only files at the flat collection root are reachable.Suggested area
src/MeshWeaver.ContentCollections/— the path → (collection, relative-key) resolution used by the read path, which is distinct from the browsing/serving route code (CollectionNamedLayoutArea,ContentLayoutArea) fixed in #326 / #364. The resolver should treat the registered collection root (e.g.{node}/content) as the boundary and pass the entire remainder as the provider's relative key, rather than consuming the next segment as a collection name. A regression test reading a nested pure-ASCII path (content/sub/file.txt) through the read path would pin it.Related