siyuan-note/siyuan · error
task list item marker length should be 1
Error message
task list item marker length should be 1
What it means
The marker parameter must be exactly one character: 'x' (checked), ' ' (unchecked), or another allowed single character. buildUpdatedTaskListItemBlockDOM rejects any marker string whose length is not 1 before inspecting the block, since a checkbox marker in Markdown is a single character inside [ ].
Solutions
- Send exactly one character: marker:'x' for checked, marker:' ' (single space) for unchecked
- Strip surrounding brackets/whitespace client-side before calling the API: marker = raw.replace(/[\[\]\s]/g, '') and validate length === 1
- Map boolean state to the marker character: state ? 'x' : ' '
- Add client-side validation that rejects any marker whose length !== 1 before the request
Example fix
// before
await fetchPost('/api/block/updateTaskListItemMarker', { id, marker: '[x]' });
// after
const marker = checked ? 'x' : ' ';
if (marker.length !== 1) throw new Error('marker must be a single character');
await fetchPost('/api/block/updateTaskListItemMarker', { id, marker }); Defensive patterns
Strategy: validation
Validate before calling
if (typeof marker !== 'string' || marker.length !== 1) {
throw new Error(`marker must be a single character, got ${JSON.stringify(marker)}`);
} Type guard
const isValidMarker = (m) => typeof m === 'string' && m.length === 1 && m !== '[' && m !== ']';
Try / catch
try {
await fetchPost('/api/block/updateTaskListItemMarker', { id, marker });
} catch (e) {
if (String(e?.msg).includes('marker length should be 1')) {
const fixed = String(e.input ?? marker).replace(/[\[\]\s]/g, '').slice(0, 1);
if (fixed) return fetchPost('/api/block/updateTaskListItemMarker', { id, marker: fixed });
}
throw e;
} Prevention
- Map booleans to 'x'/' ' at one central helper instead of passing raw strings
- Strip brackets/whitespace from any user- or DOM-derived marker input
- Add an assertion in shared request helpers that marker.length === 1
When it happens
Trigger: Calling POST /api/block/updateTaskListItemMarker with marker set to "x ", "[x]", "xx", "", or a whole Markdown checkbox snippet instead of the single character.
Common situations: Clients concatenating the brackets with the mark; trimming bugs that leave whitespace; UI code passing "checked"/"true" instead of 'x'; batch items where one marker string was built by joining values.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/845a1be9c204379e.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/api/block_op.go:59
return "", errors.New("block is not a list item")
}
tree, err := filesys.LoadTree(block.Box, block.Path, luteEngine)
if err != nil {
return "", errors.New("load tree failed: " + err.Error())
}
li := treenode.GetNodeInTree(tree, id)
if li == nil {
return "", errors.New("block not found")
}
if 3 != li.ListData.Typ {
return "", errors.New("block is not a task list item")
}
if 1 != len(marker) {
return "", errors.New("task list item marker length should be 1")
}
liMarker := marker[0]
if '[' == liMarker || ']' == liMarker {
return "", errors.New("task list item marker can not be [ or ]")
}
markerNode := li.ChildByType(ast.NodeTaskListItemMarker)
if nil == markerNode {
return "", errors.New("task list item marker not found")
}
markerNode.TaskListItemMarker = liMarker
markerNode.TaskListItemChecked = ' ' != markerNode.TaskListItemMarker
treenode.RefreshUpdated(li)
return luteEngine.RenderNodeBlockDOM(li), nilView on GitHub (pinned to 9f775e8a12)