siyuan-note/siyuan · error

Field [notebook] must not be empty

Error message

Field [notebook] must not be empty

What it means

For /api/block/checkBlockRef with scope "notebook", the notebook field must be non-empty after trimming whitespace. This error fires when the provided notebook value consists only of spaces or trims to an empty string, distinguishing it from [215] which covers a fully absent/null notebook. It enforces that a real notebook ID is supplied.

Solutions

  1. Supply the actual notebook ID (format 20240101120000-xxxxxxx) rather than placeholder whitespace
  2. Validate with notebook.trim().length > 0 before sending when scope is "notebook"
  3. Read the ID from the opened notebook list (kernel /api/notebook/lsNotebooks) instead of user free-text

Example fix

// before
const notebook = input.value; // "   "
await fetchPost("/api/block/checkBlockRef", { scope: "notebook", notebook, ids });
// after
if (notebook.trim()) {
  await fetchPost("/api/block/checkBlockRef", { scope: "notebook", notebook: notebook.trim(), ids });
}
Defensive patterns

Strategy: validation

Validate before calling

if (payload.scope === 'notebook' && !payload.notebook?.trim()) throw new Error('notebook must be a non-empty ID');

Type guard

const hasRealNotebook = (p) => p.scope !== 'notebook' || (typeof p.notebook === 'string' && p.notebook.trim().length > 0);

Try / catch

try { await fetchPost('/api/block/checkBlockRef', payload); } catch (e) { if (/Field \[notebook\] must not be empty/.test(e?.message)) { /* re-fetch notebook ID from /api/notebook/lsNotebooks */ } }

Prevention

When it happens

Trigger: POST /api/block/checkBlockRef with {"scope":"notebook","notebook":" "}; a notebook variable that was whitespace because an input field was never filled with an actual ID.

Common situations: Copy-paste of an ID that lost its content; form input bound to a whitespace default; whitespace-only values passing a naive truthiness check (" " is truthy in JS) before the request is built.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at kernel/apicontract/block_remaining.go:146

				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
}

func decodeHeadingLevel(reader io.Reader) (request HeadingLevelRequest, err error) {
	fields, err := blockRequestFields(reader, "/api/block/getHeadingLevelTransaction")
	if err != nil {
		return request, err
	}
	if len(fields["level"]) == 0 || bytes.Equal(fields["level"], []byte("null")) || json.Unmarshal(fields["level"], &request.Level) != nil {
		return request, errors.New("Field [level] should be of type [Number]")
	}
	var entries []json.RawMessage
	if raw := fields["ids"]; len(raw) > 0 && !bytes.Equal(raw, []byte("null")) && json.Unmarshal(raw, &entries) == nil {
		request.IDs = []string{}
		seen := map[string]bool{}

View on GitHub (pinned to 9f775e8a12)