siyuan-note/siyuan · error

Field [ ] should be of type [Array]

Error message

Field [%s] should be of type [Array]

What it means

The SiYuan kernel validates fields of the /api/block/checkBlockRef request body individually. When a declared array field (ids, exactIDs, deletedIDs, or paths) is present but its JSON value fails to unmarshal into a JSON array, the kernel rejects the request with this error. It means the field's value has the wrong JSON type (e.g. a string, number, or object) where an array is required.

Solutions

  1. Wrap the value in JSON array brackets: "ids": ["<block-id>"]
  2. Ensure the client serializes the field as an array even when it has one element
  3. Check for null handling: null is treated as missing and raises 'Field [...] is required' instead, so supply a real array
  4. Verify the JSON body parses correctly (no nested quoting) before sending

Example fix

// before
{ "scope": "blocks", "ids": "20240101120000-abcdefg" }
// after
{ "scope": "blocks", "ids": ["20240101120000-abcdefg"] }
Defensive patterns

Strategy: validation

Validate before calling

function assertStringArray(v) { if (!Array.isArray(v) || !v.every(x => typeof x === 'string')) throw new TypeError('field must be a string array'); }

Type guard

const isStringArray = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string');

Try / catch

try { await fetchPost('/api/block/checkBlockRef', payload); } catch (e) { if (/should be of type \[Array\]/.test(e?.message)) { /* fix payload shape */ } else { throw e; } }

Prevention

When it happens

Trigger: POST /api/block/checkBlockRef with scope "blocks" and ids given as a single string like "ids":"20240101120000-abcdefg" instead of ["20240101120000-abcdefg"]; scope "documents" with paths as a string instead of an array; or any of exactIDs/deletedIDs passed as a non-array JSON value.

Common situations: Wrapping a single block ID without array brackets when scripting the API; older plugin code written against a loose client that silently coerced scalars to arrays; building the payload with template string interpolation that drops the brackets; JSON serialization sending an object or quoted CSV string.

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


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/e3312b74e9bb6e5d. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/block_remaining.go:89

	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 {
			return nil, fmt.Errorf("Field [%s] must not be empty", key)
		}
		var values []string
		seen := map[string]bool{}
		for _, entry := range entries {
			var value string
			if json.Unmarshal(entry, &value) != nil || strings.TrimSpace(value) == "" {
				return nil, fmt.Errorf("Field [%s] should contain non-empty strings", key)
			}
			if !seen[value] {
				values = append(values, value)
				seen[value] = true
			}
		}
		return values, nil
	}

View on GitHub (pinned to 9f775e8a12)