Hello everyone,
I encountered an unexpected behavior while working with the SiYuan Kernel API, specifically** /api/filetree/createDocWithMd, when creating documents whose titles contain **/.
The API appears to interpret** **/ inside the document title as a path separator, resulting in unintended directory creation rather than treating it as part of the document name.
Environment
- SiYuan / Sedge: 3.8.3+
- OS: macOS ARM64 / Cross-platform
- Interface: Kernel HTTP API —** **
/api/filetree/createDocWithMd
Issue
For example, if I attempt to create a document with the path:
/Documentation/Overview (kernel/api)
I would expect a single document named:
Overview (kernel/api)
However, the actual result is:
Documentation/
└── Overview (kernel/
└── api).sy
Similarly, creating:
/Notes/Programming in C/C++
results in:
Notes/
└── Programming in C/
└── C++.sy
This happens silently, which can be particularly problematic for import scripts and plugins that generate documents programmatically.
Steps to reproduce
Send a request to:
POST /api/filetree/createDocWithMd
For example:
curl -X POST http://127.0.0.1:6806/api/filetree/createDocWithMd \
-H "Authorization: Token <YOUR_API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"notebook": "<YOUR_NOTEBOOK_ID>",
"path": "/Notes/Programming in C/C++",
"markdown": "# Introduction\n\nContent goes here."
}'
The resulting filesystem structure contains a** Programming in C directory with C++ as a child document instead of creating a single document named **Programming in C/C++.
Possible root cause
Looking at** **kernel/api/filetree.go, the relevant logic appears to be:
baseName := path.Base(hPath)
dir := path.Dir(hPath)
r, _ := regexp.Compile("\r\n|\r|\n|\u2028|\u2029|\t|/")
baseName = r.ReplaceAllString(baseName, "")
if 512 < utf8.RuneCountInString(baseName) {
baseName = gulu.Str.SubStr(baseName, 512)
}
hPath = path.Join(dir, baseName)
The potential issue is that** path.Dir() and path.Base() are evaluated **before / is sanitized.
Since Go's** path package treats **/ as a path separator, a slash contained in what the caller intended to be the document title is already interpreted as directory hierarchy before the sanitization step occurs.
Expected behavior
I think the API should either:
- Sanitize the document title before resolving the directory structure,** **or
- Explicitly reject**
/in document titles with a validation error, making it clear that **/is reserved for path hierarchy.
Possible approaches could be:
- Separate the folder path and document name into distinct API parameters.
- Sanitize the target title before calling**
path.Dir()/ **path.Base(). - Return a validation error such as:
{
"code": -1,
"msg": "Document title cannot contain slashes"
}
The main concern is the** **silent creation of unintended directories, especially when this API is used by automated importers, plugins, or other tooling.
Has anyone else encountered this behavior when working with import scripts or plugins?
I’d also appreciate the maintainers' thoughts on whether** / is intentionally supported in document titles and, if so, how it is expected to be handled by **createDocWithMd.
Thanks.
Welcome to here!
Here we can learn from each other how to use SiYuan, give feedback and suggestions, and build SiYuan together.
Signup About