{"record":{"id":"8cba03847b91f2be","repo":"siyuan-note/siyuan","slug":"invalid-block-swap-options","errorCode":null,"errorMessage":"invalid block swap options","messagePattern":"invalid block swap options","errorType":"exception","errorClass":"TxErr","httpStatus":null,"severity":"error","filePath":"kernel/model/transaction_block_swap.go","lineNumber":53,"sourceCode":"\tif len(tx.DoOperations) != 1 {\n\t\treturn fail(errors.New(\"block swap must be submitted as a separate transaction\"))\n\t}\n\tif tx.isReplay {\n\t\tif operation.blockSwapState == nil {\n\t\t\treturn fail(errors.New(\"block swap undo state is unavailable\"))\n\t\t}\n\t\tif err := tx.replayBlockSwap(operation); err != nil {\n\t\t\treturn fail(err)\n\t\t}\n\t\treturn nil\n\t}\n\tdata, err := json.Marshal(operation.Data)\n\tif err != nil {\n\t\treturn fail(err)\n\t}\n\tvar options blockSwapOptions\n\tif err = json.Unmarshal(data, &options); err != nil || options.IncludeChildren == nil || options.OriginalToEmbed == nil {\n\t\treturn fail(errors.New(\"invalid block swap options\"))\n\t}\n\trefTree, err := tx.loadTree(operation.ID)\n\tif err != nil {\n\t\treturn fail(err)\n\t}\n\tdefTree, err := tx.loadTree(operation.BlockID)\n\tif err != nil {\n\t\treturn fail(err)\n\t}\n\tif !IsSameCryptoBoundary(refTree.Box, defTree.Box) {\n\t\treturn fail(errors.New(\"cannot swap blocks across encrypted notebook boundaries\"))\n\t}\n\tref := treenode.GetNodeInTree(refTree, operation.ID)\n\tdef := treenode.GetNodeInTree(defTree, operation.BlockID)\n\tif err = validateBlockSwap(ref, def, *options.IncludeChildren); err != nil {\n\t\treturn fail(err)\n\t}\n\ttrees := []*parse.Tree{refTree}","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/transaction_block_swap.go#L35-L71","documentation":"The swap operation's Data payload failed to unmarshal into blockSwapOptions, or one of the required boolean options IncludeChildren or OriginalToEmbed was nil. Both option pointers must be present and non-null so the kernel knows whether child blocks and embed blocks participate in the swap.","triggerScenarios":"Calling the transactions API with a swap-block-ref operation whose data JSON omits 'includeChildren' or 'originalToEmbed', or whose data is not valid JSON / not an options object.","commonSituations":"Hand-written API calls or scripts constructing swap operations; plugin code updated to a newer options schema that renamed fields; sending the raw block content instead of an options object in data.","solutions":["Include both options in the operation data, e.g. {\"includeChildren\":true,\"originalToEmbed\":false}","Ensure operation.Data is a JSON object, not a string or block content","Verify field names match the current blockSwapOptions schema (camelCase)"],"exampleFix":"// before\n{\"action\":\"swap-block-ref\",\"id\":\"<refId>\",\"blockID\":\"<defId>\",\"data\":{\"includeChildren\":true}}\n// after\n{\"action\":\"swap-block-ref\",\"id\":\"<refId>\",\"blockID\":\"<defId>\",\"data\":{\"includeChildren\":true,\"originalToEmbed\":false}}","handlingStrategy":"validation","validationCode":"const d = op.data;\nif (typeof d !== 'object' || d === null || typeof d.includeChildren !== 'boolean' || typeof d.originalToEmbed !== 'boolean') {\n  throw new Error('swap-block-ref data requires includeChildren and originalToEmbed booleans');\n}","typeGuard":"function isValidSwapOptions(d) {\n  return typeof d === 'object' && d !== null && typeof (d).includeChildren === 'boolean' && typeof (d).originalToEmbed === 'boolean';\n}","tryCatchPattern":null,"preventionTips":["Always set both includeChildren and originalToEmbed explicitly","Keep swap options construction in one shared helper validated against the schema","Check field names are camelCase per blockSwapOptions"],"tags":["validation","json","block-swap","api"],"backgroundTag":"missing-required-argument","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"}