siyuan-note/siyuan · error
invalid block ref check scope
Error message
invalid block ref check scope
What it means
The scope field of /api/block/checkBlockRef accepts only "blocks", "documents", or "notebook" (empty defaults to "blocks"). Any other non-empty scope value falls through to the switch default and is rejected with this error. It is an enum-validation failure on the request's scope parameter.
Solutions
- Use exactly one of "blocks", "documents", or "notebook"
- Omit scope (or send null) to get the default "blocks" behavior
- Normalize the caller's value with toLowerCase() and map synonyms to the valid enum before sending
Example fix
// before
await fetchPost("/api/block/checkBlockRef", { scope: "documents", paths });
// after (typo: valid scope is "documents" only; "document" is rejected)
await fetchPost("/api/block/checkBlockRef", { scope: "documents", paths });
// for per-doc use the singular name is invalid; choose scope per intent:
// "blocks" + ids | "documents" + paths | "notebook" + notebook Defensive patterns
Strategy: type-guard
Validate before calling
const SCOPES = ['blocks', 'documents', 'notebook'];
if (!SCOPES.includes(scope)) throw new Error(`unsupported scope: ${scope}`); Type guard
const isValidScope = (s) => s === undefined || s === null || ['blocks', 'documents', 'notebook'].includes(s);
Try / catch
try { await fetchPost('/api/block/checkBlockRef', payload); } catch (e) { if (/invalid block ref check scope/.test(e?.message)) { payload.scope = 'blocks'; /* retry with default */ } } Prevention
- Use a union type 'blocks' | 'documents' | 'notebook' for scope in TypeScript
- Copy scope values from API docs, never from UI labels
- Rely on the default (omit scope) when the intent is block-level checks
When it happens
Trigger: POST /api/block/checkBlockRef with "scope": "doc", "scope": "Blocks", "scope": "document", or any misspelled/unsupported value.
Common situations: Plugin code guessing scope names instead of copying the API enum; case-sensitivity mistakes ("Blocks" vs "blocks"); translated UI labels passed directly as the scope value; version drift where code used a scope name from a different endpoint.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Field [mode] must be 0 or 1
- invalid pinned document action
- AI editor action must not be empty
- block [ ] type is locked: expected , got
- block swap requires two non-document blocks
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/0dad3dd5651bdd14.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/block_remaining.go:134
if request.DeletedIDs, err = readArray("deletedIDs", false, false); err != nil {
return
}
case "documents":
request.Paths, err = readArray("paths", true, true)
return
case "notebook":
// 附带块 ID 只参与租约准入,沿用仅收集字符串的规则。
var entries []json.RawMessage
if json.Unmarshal(fields["ids"], &entries) == nil {
for _, entry := range entries {
var id string
if !bytes.Equal(entry, []byte("null")) && json.Unmarshal(entry, &id) == nil {
request.IDs = append(request.IDs, id)
}
}
}
default:
return request, errors.New("invalid block ref check scope")
}
if raw := fields["notebook"]; len(raw) != 0 && !bytes.Equal(raw, []byte("null")) {
if json.Unmarshal(raw, &request.Notebook) != nil {
return request, errors.New("Field [notebook] should be of type [String]")
}
} else if request.Scope == "notebook" {
return request, errors.New("Field [notebook] is required")
}
if request.Scope == "notebook" {
request.Notebook = strings.TrimSpace(request.Notebook)
if request.Notebook == "" {
return request, errors.New("Field [notebook] must not be empty")
}
}
_ = json.Unmarshal(fields["id"], &request.ID)
return
}
View on GitHub (pinned to 9f775e8a12)