siyuan-note/siyuan · error

localized block-not-found message (Conf.Language(15)) with b

Error message

localized block-not-found message (Conf.Language(15)) with block ID

What it means

GetHeadingDeleteTransaction builds the transaction that removes a heading and its children. Before inspecting the node it looks the block up in the parsed tree; if no node exists for the given ID it returns the localized block-not-found message (Conf.Language(15)) formatted with the block ID. The heading ID does not correspond to any existing block in the document tree.

Source

Thrown at kernel/model/block.go:843

	if !sameTree {
		if err = indexWriteTreeUpsertQueue(defTree); err != nil {
			return
		}
	}
	FlushTxQueue()
	util.ReloadUI()
	return
}

func GetHeadingDeleteTransaction(id string) (transaction *Transaction, err error) {
	tree, err := LoadTreeByBlockID(id)
	if err != nil {
		return
	}

	node := treenode.GetNodeInTree(tree, id)
	if nil == node {
		err = fmt.Errorf(Conf.Language(15), id)
		return
	}

	if ast.NodeHeading != node.Type {
		return
	}

	var nodes []*ast.Node
	nodes = append(nodes, node)
	nodes = append(nodes, treenode.HeadingChildren(node)...)
	hiddenNodes := map[string]bool{}
	for _, hidden := range treenode.CollectFoldHiddenNodes(node.Parent) {
		hiddenNodes[hidden.ID] = true
	}

	transaction = &Transaction{}
	luteEngine := util.NewLute()
	for _, n := range nodes {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Refresh the block ID from the current document (re-read the block via SQL/API) before calling the transaction builder
  2. Confirm the document tree is indexed correctly (rebuild the index for the notebook if .sy files were edited externally)
  3. Check that the ID is a valid 14-character node ID and belongs to the intended box/doc
  4. If concurrent modification is possible, re-run the operation after syncing/reloading the document

Example fix

// before
ops, err := GetHeadingDeleteTransaction(staleHeadingID)
// after
if !treenode.IsNodeExist(staleHeadingID) { // or re-query the block first
    return fmt.Errorf("heading %s no longer exists; refresh ID", staleHeadingID)
}
ops, err := GetHeadingDeleteTransaction(staleHeadingID)
Defensive patterns

Strategy: validation

Validate before calling

// before building the delete transaction
if (!blockExists(headingID)) {
  throw new Error(`heading ${headingID} no longer exists`);
}

Type guard

function hasNode(id) {
  return typeof id === "string" && /^\d{14}$/.test(id) && treeHasNode(id);
}

Prevention

When it happens

Trigger: Calling GetHeadingDeleteTransaction (directly or via getHeadingDeleteTransaction) with a heading ID that no longer exists — the block was deleted in another session, the ID is mistyped, or the .sy file changed on disk without reindexing.

Common situations: Stale block IDs held by plugins/scripts after content changed, concurrent edits removing the heading, corrupted or manually edited .sy files, or a race between fetching the ID and building the transaction.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/6842ac17c6a1f274. Report an issue: GitHub.