{"record":{"id":"c21810fabd2cc2db","repo":"siyuan-note/siyuan","slug":"responsehtml-msg","errorCode":null,"errorMessage":"responseHTML.msg","messagePattern":"responseHTML\\.msg","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/src/protyle/wysiwyg/commonHotkey.ts","lineNumber":365,"sourceCode":"        lastElement.after(tempElement);\n        doOperations.push({\n            action: \"insert\",\n            data: tempElement.outerHTML,\n            id: newId,\n            previousID: lastElement.getAttribute(\"data-node-id\"),\n        });\n        undoOperations.push({\n            action: \"delete\",\n            id: newId,\n        });\n        if (item.getAttribute(\"data-type\") === \"NodeHeading\" && item.getAttribute(\"fold\") === \"1\") {\n            foldHeadingIds.push({oldId: item.getAttribute(\"data-node-id\"), newId});\n            const responseHTML = await fetchSyncPost(\"/api/block/getHeadingChildrenDOM\", {\n                id: item.getAttribute(\"data-node-id\"),\n                removeFoldAttr: false,\n            });\n            if (responseHTML.code !== 0) {\n                throw new Error(responseHTML.msg);\n            }\n            const foldElement = document.createElement(\"template\");\n            foldElement.innerHTML = normalizeHTMLAssetIFrameBlockDOM(responseHTML.data);\n            let previousID = newId;\n            Array.from(foldElement.content.children).slice(1).forEach((childItem: HTMLElement) => {\n                childItem.removeAttribute(\"parent-heading\");\n                const foldedIDs = new Map<string, string>();\n                childItem.querySelectorAll(\"[data-node-id]\").forEach(subItem => {\n                    const id = Lute.NewNodeID();\n                    foldedIDs.set(subItem.getAttribute(\"data-node-id\"), id);\n                    subItem.setAttribute(\"data-node-id\", id);\n                    clearBlockElement(subItem);\n                });\n                const newChildId = Lute.NewNodeID();\n                foldedIDs.set(childItem.getAttribute(\"data-node-id\"), newChildId);\n                childItem.setAttribute(\"data-node-id\", newChildId);\n                clearBlockElement(childItem);\n                remapTabsDOMIDs(childItem, foldedIDs);","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/app/src/protyle/wysiwyg/commonHotkey.ts#L347-L383","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait duplicateBlock(item);\n// after\ntry {\n    await duplicateBlock(item);\n} catch (e) {\n    showMessage(e.message || \"duplicate failed\");\n    reloadProtyle(protyle);\n}","handlingStrategy":"try-catch","validationCode":"const info = await fetchSyncPost(\"/api/block/getBlockInfo\", {id: item.getAttribute(\"data-node-id\")});\nif (info.code !== 0) return; // block gone\nawait duplicateBlock(item);","typeGuard":null,"tryCatchPattern":"try { await duplicateBlock(item); } catch (e) { showMessage(e.message); reloadProtyle(protyle); }","preventionTips":["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"],"tags":["api","network","block-not-found"],"backgroundTag":"api-error-response","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}