siyuan-note/siyuan · error · Error
response.msg
Error message
response.msg
What it means
foldBlocksRecursively0 fetches all child DOM of a heading via /api/block/getHeadingChildrenDOM. When the kernel responds with a non-zero code, the raw response.msg text is thrown as an Error so the recursive fold operation aborts with the backend's message.
Solutions
- Catch the error in the fold action handler and show response.msg to the user, then refresh/ Reload the document to get fresh node IDs
- Re-index the notebook (Rebuild Index) if block IDs are stale due to index/database mismatch
- Retry the fold after the document tree has been refreshed so element carries a valid data-node-id
- Check kernel logs for the underlying error returned by getHeadingChildrenDOM
Example fix
// before
foldBlocksRecursively(protyle, element); // unhandled throw on API failure
// after
try {
await foldBlocksRecursively(protyle, element);
} catch (e) {
showMessage(e.message);
reloadProtyle(protyle, false); // refresh stale DOM
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!element.getAttribute("data-node-id")) {
throw new Error("Cannot fold: element has no data-node-id");
} Type guard
const isApiResponse = (r: unknown): r is {code: number, msg: string, data: unknown} =>
typeof r === "object" && r !== null && "code" in r && "msg" in r; Try / catch
try {
await foldBlocksRecursively(protyle, element);
} catch (e) {
showMessage(e.message || "Fold failed");
reloadProtyle(protyle, false);
} Prevention
- Refresh protyle content after sync/remote edits before folding
- Rebuild notebook index when block lookups fail persistently
- Check that the block still exists before recursive fold
- Watch kernel logs for getHeadingChildrenDOM failures
When it happens
Trigger: Calling foldBlocksRecursively on a NodeHeading whose /api/block/getHeadingChildrenDOM request fails — e.g. the block ID no longer exists (stale DOM), the notebook is closed/syncing, or the kernel returned an internal error for that block.
Common situations: Document changed in another window/sync while folding, leaving a stale data-node-id; kernel busy or restarting; database index out of sync with .sy files so the block lookup fails.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- block updates are empty
- unsupported block operation
- Access to encrypted notebook data is not supported via this…
- AI editor action must not be empty
- AI editor action not found
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/a1f3ad259a4a30ef.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/protyle/util/blockFold.ts:330
};
const addScope = (scope: ParentNode, occurrenceID?: string) => {
if (scope instanceof Element) {
addCandidate(scope, occurrenceID);
}
scope.querySelectorAll("[data-type='NodeHeading'], .li, .bq, .sb, .callout").forEach(element => {
addCandidate(element, occurrenceID);
});
};
const scopes = await Promise.all(nodeElements.map(async (element) => {
let fullHTML = "";
if (element.getAttribute("data-type") === "NodeHeading") {
const response = await fetchSyncPost("/api/block/getHeadingChildrenDOM", {
id: element.getAttribute("data-node-id"),
removeFoldAttr: false,
});
if (response.code !== 0) {
throw new Error(response.msg);
}
fullHTML = response.data;
} else if (element.querySelector('[data-type="NodeHeading"][fold="1"]')) {
const response = await fetchSyncPost("/api/block/getBlockDOM", {
id: element.getAttribute("data-node-id"),
notebook: protyle.notebookId,
});
if (response.code !== 0) {
throw new Error(response.msg);
}
fullHTML = response.data.dom;
}
return {element, fullHTML, occurrenceID: getViewFoldOccurrenceID(protyle, element)};
}));
scopes.forEach(({element, fullHTML, occurrenceID}) => {
if (fullHTML) {
const template = document.createElement("template");
template.innerHTML = fullHTML;View on GitHub (pinned to 9f775e8a12)