siyuan-note/siyuan · error

Bookmark cannot be empty

Error message

Bookmark cannot be empty

What it means

model.RenameBookmark rejects a new bookmark name that is empty after strings.TrimSpace. This is the second validation, after the marker check, and uses localized message 126 ('Bookmark cannot be empty'). An empty string is the API-supported way to signal invalid input, not a delete — bookmarks are removed by unsetting them on blocks, not renamed to nothing.

Solutions

  1. Require a non-empty trimmed name in the UI before calling the API
  2. To remove a bookmark from blocks, set/unset the 'bookmark' attribute via setBlockAttrs instead of renaming to empty
  3. Guard scripts: skip the call when !newBookmark.trim()

Example fix

// before
renameBookmark(oldName, ''); // error

// after
if (newName.trim()) { renameBookmark(oldName, newName.trim()); }
Defensive patterns

Strategy: validation

Validate before calling

const name = String(newBookmark ?? '').trim();
if (!name) throw new Error('bookmark name required');

Prevention

When it happens

Trigger: POST /api/bookmark/renameBookmark with newBookmark '', ' ', or a string that is only whitespace; also a name that was entirely marker characters is caught earlier, not here.

Common situations: Forms that submit before the user types a name, or scripts that pass an undefined/null coerced to '' when the desired name field is missing.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/1f94c7e08043e391. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/bookmark.go:103

		util.RandomSleep(50, 150)
	}

	indexHistoryDir(filepath.Base(historyDir), util.NewLute())
	sql.FlushQueue()

	util.ReloadUI()
	return
}

func RenameBookmark(oldBookmark, newBookmark string) (err error) {
	if invalidChar := treenode.ContainsMarker(newBookmark); "" != invalidChar {
		return fmt.Errorf(Conf.Language(112), invalidChar)
	}

	newBookmark = strings.TrimSpace(newBookmark)
	if "" == newBookmark {
		return errors.New(Conf.Language(126))
	}

	if oldBookmark == newBookmark {
		return
	}

	util.PushEndlessProgress(Conf.Language(110))
	defer util.ClearPushProgress(100)

	bookmarks := sql.QueryBookmarkBlocks()
	treeBlocks := map[string][]string{}
	for _, bm := range bookmarks {
		if blocks, ok := treeBlocks[bm.RootID]; !ok {
			treeBlocks[bm.RootID] = []string{bm.ID}
		} else {
			treeBlocks[bm.RootID] = append(blocks, bm.ID)
		}
	}

View on GitHub (pinned to afa823b6b4)