siyuan-note/siyuan · warning
SQL search mode does not support the replace operation…
Error message
SQL search mode does not support the replace operation, please use another search method
What it means
FindReplaceInBox explicitly rejects SQL search mode (method == 2): replacing text found by a raw SQL query is not supported because SQL matches cannot be reliably mapped back to editable text ranges. The error message is i18n language string 132 telling the user to choose another search method.
Solutions
- Use method 0 (text), 1 (query syntax) or 3 (regex) for the replace operation
- Run the SQL query separately to collect IDs, then replace per block with a supported method
- Update the calling UI to disable or remap SQL mode when a replacement is requested
Example fix
// before
err := model.FindReplace(k, r, types, ids, paths, boxes, method /* 2 = SQL */, replaceTypes)
// after
if method == 2 {
method = 0 // fall back to text search for replace
}
err := model.FindReplace(k, r, types, ids, paths, boxes, method, replaceTypes) Defensive patterns
Strategy: validation
Validate before calling
if (method === 2 && replacement) { throw new Error('SQL mode cannot replace; use text/query/regex') } Try / catch
try { await api.findReplace(k, r, { method }) } catch (e) { if (String(e).includes('replace operation')) { notifyUserToChangeSearchMethod(); } else throw e } Prevention
- Map method codes explicitly (0=text, 1=query, 2=SQL, 3=regex) and guard SQL at the UI level
- Never send a replacement string with method=2
- Offer users a fallback method when they arrive at SQL mode with replace enabled
When it happens
Trigger: Calling FindReplace or FindReplaceInBox with method=2 (SQL) and a non-empty replacement — the check fires before any search runs.
Common situations: Scripts or UI automation reusing the last search method (SQL) when issuing a replace; users switching from search-only to replace without changing the method dropdown.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/774c4e36d3187221.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/search.go:636
}
boxIDs = gulu.Str.RemoveDuplicatedElem(boxIDs)
boxNames := Conf.BoxNames(boxIDs)
for _, b := range blocks {
name := boxNames[b.Box]
b.HPath = util.EscapeHTML(name) + b.HPath
}
}
func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids []string, paths, boxes []string, types, subTypes map[string]bool, method, orderBy, groupBy int) (err error) {
// orderBy 和 groupBy 仅用于兼容现有调用,替换目标不依赖搜索结果的展示顺序和分组方式。
return FindReplaceInBox(keyword, replacement, replaceTypes, ids, paths, boxes, types, subTypes, method, "")
}
// FindReplaceInBox 与 FindReplace 一致,但按 boxID 路由到加密 db 或全局 db。
func FindReplaceInBox(keyword, replacement string, replaceTypes map[string]bool, ids []string, paths, boxes []string, types, subTypes map[string]bool, method int, boxID string) (err error) {
// method:0:文本,1:查询语法,2:SQL,3:正则表达式
if 2 == method {
err = errors.New(Conf.Language(132))
return
}
if 1 == method {
// 将查询语法等价于关键字,因为 keyword 参数已经是结果关键字了
// Find and replace supports query syntax https://github.com/siyuan-note/siyuan/issues/14937
method = 0
}
// No longer trim spaces for the keyword and replacement https://github.com/siyuan-note/siyuan/issues/9229
if keyword == replacement {
return
}
r, _ := regexp.Compile(keyword)
escapedKey := util.EscapeHTML(keyword)
escapedKey = strings.ReplaceAll(escapedKey, """, """)
escapedKey = strings.ReplaceAll(escapedKey, "'", "'")View on GitHub (pinned to 9f775e8a12)