siyuan-note/siyuan · error
Field [scope] should be of type [String]
Error message
Field [scope] should be of type [String]
What it means
The checkBlockRef endpoint's scope field, when present, must be a JSON string (or absent, in which case it defaults to "blocks"). Explicit JSON null also counts as a type error. This guards the scope selector that steers which reference kinds are checked.
Solutions
- Send scope as a quoted string, e.g. {"scope":"blocks"} or the supported child-document scope value.
- Omit the scope key entirely to get the "blocks" default.
- Replace null with key omission on the client before serializing.
- If the value comes from a select input, ensure it yields a single string, not an array or number.
Example fix
// before
{"ids": ["20240101120000-abcdefg"], "scope": null}
// after
{"ids": ["20240101120000-abcdefg"]} // scope omitted, defaults to "blocks" Defensive patterns
Strategy: type-guard
Validate before calling
if ("scope" in payload && (payload.scope === null || typeof payload.scope !== "string")) { delete payload.scope; } Type guard
const isScope = (v) => typeof v === "string" && v.length > 0;
Try / catch
try {
await post("/api/block/checkBlockRef", payload);
} catch (e) {
if (String(e.message).includes("Field [scope] should be of type [String]")) {
delete payload.scope; // fall back to the "blocks" default
await post("/api/block/checkBlockRef", payload);
} else { throw e; }
} Prevention
- Omit scope instead of sending null to mean 'unset'
- Constrain UI selects for scope to string values only
- Reject non-string scope values at the client boundary
- Document the default ("blocks") so callers know omission is safe
When it happens
Trigger: POSTing to /api/block/checkBlockRef with {"scope":123}, {"scope":null}, {"scope":["blocks"]}, or any non-string value for scope.
Common situations: Clients sending null to mean 'unset' (omit the key instead), arrays built from multi-select UIs, or numeric enum constants from another API mapped onto scope.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Field [ ] should be of type [Array]
- Field [ ] should be of type [ ]
- block [ ] type is locked: expected , got
- createDocTree definition must be a list
- createDocTree document must be a dictionary
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/201a426bd01a342d.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/block_remaining.go:73
func blockRequestFields(reader io.Reader, path string) (fields map[string]json.RawMessage, err error) {
err = json.NewDecoder(reader).Decode(&fields)
if err != nil {
if errors.Is(err, io.EOF) {
err = errors.New("the request body is empty or truncated (EOF)")
}
err = fmt.Errorf("Parses request [%s] failed: %s", path, err)
}
return
}
func decodeCheckBlockRef(reader io.Reader) (request CheckBlockRefRequest, err error) {
fields, err := blockRequestFields(reader, "/api/block/checkBlockRef")
if err != nil {
return request, err
}
if raw, present := fields["scope"]; present {
if bytes.Equal(raw, []byte("null")) || json.Unmarshal(raw, &request.Scope) != nil {
return request, errors.New("Field [scope] should be of type [String]")
}
}
if strings.TrimSpace(request.Scope) == "" {
request.Scope = "blocks"
}
readArray := func(key string, required, nonempty bool) ([]string, error) {
raw, present := fields[key]
if !present && !required {
return nil, nil
}
if !present || bytes.Equal(raw, []byte("null")) {
return nil, fmt.Errorf("Field [%s] is required", key)
}
var entries []json.RawMessage
if json.Unmarshal(raw, &entries) != nil {
return nil, fmt.Errorf("Field [%s] should be of type [Array]", key)
}
if nonempty && len(entries) == 0 {View on GitHub (pinned to 9f775e8a12)