siyuan-note/siyuan · error · Error
responseTransaction.msg
Error message
responseTransaction.msg
What it means
While rebuilding undo state after a move operation, a transaction request sent via fetchSyncPost (responseTransaction) came back with a non-zero code or an unexpected msg. The msg field surfaces the kernel's rejection of a generated transaction — commonly because an operation references a block ID that no longer exists (the blocks were moved/deleted concurrently), the notebook is locked or read-only, or a permission check failed. The surrounding loop over copyFoldHeadingIds means folded-heading children are re-fetched per iteration, so any child that vanished mid-move triggers this on that iteration.
Solutions
- Inspect responseTransaction.code before using the payload and skip/collect the failing folded-heading child rather than applying partial undo operations
- Batch the per-child transaction requests or resolve all child IDs up front to shrink the race window with concurrent modifications
- Show the returned msg to the user via a toast so kernel-side rejections (locked notebook, missing block) are visible instead of silently dropped
- Guard the move when the target or source notebook is locked/syncing before generating transactions
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at app/src/protyle/util/editorCommonEvent.ts:707 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/2164709f2789dc4a.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/protyle/util/editorCommonEvent.ts:707
});
updateListOrder(orderList.element, orderList.start);
Array.from(orderList.element.children).forEach((item) => {
if (item.classList.contains("protyle-attr")) {
return;
}
doOperations.push({
action: "update",
id: item.getAttribute("data-node-id"),
data: item.outerHTML
});
});
});
undoOperations.reverse();
for (let j = 0; j < copyFoldHeadingIds.length; j++) {
const childrenItem = copyFoldHeadingIds[j];
const responseTransaction = await fetchSyncPost("/api/block/getHeadingInsertTransaction", {id: childrenItem.oldId});
if (responseTransaction.code !== 0) {
throw new Error(responseTransaction.msg);
}
responseTransaction.data.doOperations.splice(0, 1);
responseTransaction.data.doOperations[0].previousID = childrenItem.newId;
responseTransaction.data.undoOperations.splice(0, 1);
doOperations.push(...responseTransaction.data.doOperations);
undoOperations.push(...responseTransaction.data.undoOperations);
}
return {
doOperations,
undoOperations,
newSourceElements
};
};
const dragSb = async (protyle: IProtyle, sourceElements: Element[], targetElement: Element, isBottom: boolean,
direct: "col" | "row", isCopy: boolean) => {
if (!isCopy && isDragTargetInSource(sourceElements, targetElement)) {
return;View on GitHub (pinned to 9f775e8a12)