{"record":{"id":"859d2e71d3ee0a67","repo":"siyuan-note/siyuan","slug":"task-list-item-marker-can-not-be-or","errorCode":null,"errorMessage":"task list item marker can not be [ or ]","messagePattern":"task list item marker can not be \\[ or \\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/block_op.go","lineNumber":64,"sourceCode":"\t\treturn \"\", errors.New(\"load tree failed: \" + err.Error())\n\t}\n\n\tli := treenode.GetNodeInTree(tree, id)\n\tif li == nil {\n\t\treturn \"\", errors.New(\"block not found\")\n\t}\n\n\tif 3 != li.ListData.Typ {\n\t\treturn \"\", errors.New(\"block is not a task list item\")\n\t}\n\n\tif 1 != len(marker) {\n\t\treturn \"\", errors.New(\"task list item marker length should be 1\")\n\t}\n\n\tliMarker := marker[0]\n\tif '[' == liMarker || ']' == liMarker {\n\t\treturn \"\", errors.New(\"task list item marker can not be [ or ]\")\n\t}\n\n\tmarkerNode := li.ChildByType(ast.NodeTaskListItemMarker)\n\tif nil == markerNode {\n\t\treturn \"\", errors.New(\"task list item marker not found\")\n\t}\n\n\tmarkerNode.TaskListItemMarker = liMarker\n\tmarkerNode.TaskListItemChecked = ' ' != markerNode.TaskListItemMarker\n\n\ttreenode.RefreshUpdated(li)\n\n\treturn luteEngine.RenderNodeBlockDOM(li), nil\n}\n\nvar updateTaskListItemMarker = contractHandler(apicontract.UpdateTaskListItemMarker, func(c *gin.Context, request apicontract.TaskListMarkerRequest) apicontract.Response[[]*apicontract.BlockTransaction] {\n\tret := gulu.Ret.NewResult()\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/api/block_op.go#L46-L82","documentation":"The single marker character cannot itself be '[' or ']'. Those characters are the checkbox delimiters in Markdown, so using them as the mark would produce ambiguous/unrenderable syntax like [[x]]; buildUpdatedTaskListItemBlockDOM rejects them explicitly.","triggerScenarios":"Calling the marker update API with marker:'[' or marker:']' — typically from code that slices one character out of a raw \"[x]\" string at the wrong offset, or user-supplied input passed through unvalidated.","commonSituations":"String-parsing code doing marker = raw[0] on \"[x]\" yields '['; templating that substitutes a captured bracket; accidental passing of the literal bracket when toggling state.","solutions":["Pass the semantic mark ('x', ' ', or another non-bracket character) instead of a character sliced from the raw DOM/Markdown text","Parse the current state first (e.g. data-task / data-task-checked attributes or subtype) and toggle between 'x' and ' '","Validate before the call: if (marker === '[' || marker === ']') reject the request","Escape or sanitize user input used as a custom marker"],"exampleFix":"// before\nconst marker = rawText[1] === 'x' ? rawText[1] : rawText[0]; // may yield '[' or ']'\n// after\nconst marker = isChecked ? 'x' : ' ';\nif (marker === '[' || marker === ']') throw new Error('invalid marker');","handlingStrategy":"validation","validationCode":"if (marker === '[' || marker === ']') {\n  throw new Error('marker cannot be a bracket; use x or space');\n}","typeGuard":"const isNonBracketMarker = (m) => m.length === 1 && !['[', ']'].includes(m);","tryCatchPattern":"try {\n  await fetchPost('/api/block/updateTaskListItemMarker', { id, marker });\n} catch (e) {\n  if (String(e?.msg).includes('can not be [ or ]')) {\n    return fetchPost('/api/block/updateTaskListItemMarker', { id, marker: 'x' }); // fall back to default mark\n  }\n  throw e;\n}","preventionTips":["Derive markers from semantic state (checked boolean), never from raw '[x]' text slices","Whitelist allowed marks ('x', ' ') in your request helper","Never index characters out of raw Markdown checkbox strings"],"tags":["validation","invalid-argument","siyuan","task-list"],"backgroundTag":"invalid-argument-value","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"}