Summary
Two related rough edges around directory creation via POST /api/v1/directories:
-
(bug) Creating a directory whose parent doesn't exist returns HTTP 500, even though the handler's mapErrorToStatus is already designed to return 404 for not-found (and 409 for already-exists). The FS plugins return a plain fmt.Errorf(...) that doesn't wrap the sentinel errors, so errors.Is(err, os.ErrNotExist) fails and it falls through to 500.
-
(feature) No recursive-create (mkdir -p) option — a client must create every intermediate level itself. For a system explicitly aimed at LLM agents (which naturally emit deep paths), this is a sharp edge.
Repro
curl -s -o - -w '\nHTTP %{http_code}\n' -X POST \
'http://localhost:8080/api/v1/directories?path=/memfs/a/b/c'
# {"error":"no such file or directory: /a/b"}
# HTTP 500 <-- expected 404 (or 409 for an existing dir)
Root cause (current master)
pkg/handlers/handlers.go mapErrorToStatus() correctly maps os.ErrNotExist / filesystem.ErrNotFound → 404, filesystem.ErrAlreadyExists → 409, etc. But the plugins return unwrapped errors. In pkg/plugins/localfs/localfs.go Mkdir:
// parent missing
return fmt.Errorf("parent directory does not exist: %s", filepath.Dir(path)) // ~L108
// already exists
return fmt.Errorf("directory already exists: %s", path) // ~L102
Neither wraps a sentinel, so errors.Is(...) in mapErrorToStatus can't match → 500. (memfs's Mkdir has the same shape; its message is "no such file or directory: ...".)
Suggested fixes
- Wrap the sentinels so status mapping works and is consistent across plugins (localfs, memfs, …), e.g.:
return fmt.Errorf("parent directory does not exist: %s: %w", parent, filesystem.ErrNotFound)
return fmt.Errorf("directory already exists: %s: %w", path, filesystem.ErrAlreadyExists)
- (feature) Add an optional recursive create, e.g.
POST /directories?path=/a/b/c&recursive=true (or parents=true), mapping to os.MkdirAll for localfs and the equivalent for in-memory plugins. One call to create a deep path matters for the agent-first use case.
Happy to send a PR if that's helpful. Observed via the HTTP API on the localfs and memfs plugins.
Summary
Two related rough edges around directory creation via
POST /api/v1/directories:(bug) Creating a directory whose parent doesn't exist returns HTTP 500, even though the handler's
mapErrorToStatusis already designed to return 404 for not-found (and 409 for already-exists). The FS plugins return a plainfmt.Errorf(...)that doesn't wrap the sentinel errors, soerrors.Is(err, os.ErrNotExist)fails and it falls through to500.(feature) No recursive-create (
mkdir -p) option — a client must create every intermediate level itself. For a system explicitly aimed at LLM agents (which naturally emit deep paths), this is a sharp edge.Repro
Root cause (current master)
pkg/handlers/handlers.gomapErrorToStatus()correctly mapsos.ErrNotExist/filesystem.ErrNotFound→ 404,filesystem.ErrAlreadyExists→ 409, etc. But the plugins return unwrapped errors. Inpkg/plugins/localfs/localfs.goMkdir:Neither wraps a sentinel, so
errors.Is(...)inmapErrorToStatuscan't match →500. (memfs'sMkdirhas the same shape; its message is"no such file or directory: ...".)Suggested fixes
POST /directories?path=/a/b/c&recursive=true(orparents=true), mapping toos.MkdirAllfor localfs and the equivalent for in-memory plugins. One call to create a deep path matters for the agent-first use case.Happy to send a PR if that's helpful. Observed via the HTTP API on the
localfsandmemfsplugins.