siyuan-note/siyuan · error · Error
responseHTML.msg
Error message
responseHTML.msg
What it means
duplicateBlock fetches child heading DOM from the kernel via /api/block/getHeadingChildrenDOM. If the kernel returns a non-zero code, the raw server message string is thrown as a plain Error. It is a pass-through of a kernel API failure (e.g. block not found) into the frontend exception path.
Solutions
- Verify the block ID still exists (/api/block/getBlockInfo) before duplicating
- Re-query the DOM for a fresh data-node-id if the document was re-rendered
- Catch the error and show the kernel message, then reload the affected document
- Retry after the sync/index queue settles if a sync race is suspected
Example fix
// before
await duplicateBlock(item);
// after
try {
await duplicateBlock(item);
} catch (e) {
showMessage(e.message || "duplicate failed");
reloadProtyle(protyle);
} Defensive patterns
Strategy: try-catch
Validate before calling
const info = await fetchSyncPost("/api/block/getBlockInfo", {id: item.getAttribute("data-node-id")});
if (info.code !== 0) return; // block gone
await duplicateBlock(item); Try / catch
try { await duplicateBlock(item); } catch (e) { showMessage(e.message); reloadProtyle(protyle); } Prevention
- Verify block existence before duplicating
- Re-read data-node-id from the DOM after any re-render or undo/redo
- Reload the document after concurrent sync conflicts
When it happens
Trigger: Calling duplicateBlock (app/src/protyle/wysiwyg/commonHotkey.ts:365) on a heading item whose data-node-id no longer exists in the kernel — typically because the document was deleted/concurrently changed or the block ID is stale after an undo/redo or sync race.
Common situations: Duplicating a heading right after another client deleted its children via sync; stale DOM references after the block tree was re-indexed; kernel unavailable (workspace closed) while the UI still holds the node.
Related errors
- Failed to obtain cloud info
- Failed to remove agent session
- generate image failed
- response.msg
- Access to encrypted notebook data is not supported via this…
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/c21810fabd2cc2db.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/protyle/wysiwyg/commonHotkey.ts:365
lastElement.after(tempElement);
doOperations.push({
action: "insert",
data: tempElement.outerHTML,
id: newId,
previousID: lastElement.getAttribute("data-node-id"),
});
undoOperations.push({
action: "delete",
id: newId,
});
if (item.getAttribute("data-type") === "NodeHeading" && item.getAttribute("fold") === "1") {
foldHeadingIds.push({oldId: item.getAttribute("data-node-id"), newId});
const responseHTML = await fetchSyncPost("/api/block/getHeadingChildrenDOM", {
id: item.getAttribute("data-node-id"),
removeFoldAttr: false,
});
if (responseHTML.code !== 0) {
throw new Error(responseHTML.msg);
}
const foldElement = document.createElement("template");
foldElement.innerHTML = normalizeHTMLAssetIFrameBlockDOM(responseHTML.data);
let previousID = newId;
Array.from(foldElement.content.children).slice(1).forEach((childItem: HTMLElement) => {
childItem.removeAttribute("parent-heading");
const foldedIDs = new Map<string, string>();
childItem.querySelectorAll("[data-node-id]").forEach(subItem => {
const id = Lute.NewNodeID();
foldedIDs.set(subItem.getAttribute("data-node-id"), id);
subItem.setAttribute("data-node-id", id);
clearBlockElement(subItem);
});
const newChildId = Lute.NewNodeID();
foldedIDs.set(childItem.getAttribute("data-node-id"), newChildId);
childItem.setAttribute("data-node-id", newChildId);
clearBlockElement(childItem);
remapTabsDOMIDs(childItem, foldedIDs);View on GitHub (pinned to 9f775e8a12)