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

Returned by buildUpdatedTaskListItemMarker when the `marker` argument to the /api/block/updateTaskListItemMarker endpoint is not exactly one character long. The kernel updates a task-list-item checkbox by replacing its single status glyph, so any other length (empty string, multi-char like "[x]", "xx") is rejected before the tree is mutated.

Source

Thrown at kernel/api/block_op.go:74

		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), nil

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Send a single character for `marker`: a space ' ' to uncheck, 'x' to check, or another non-bracket glyph.
  2. If your data is in GFM form like '[x]', strip the brackets before calling: marker = raw[1:2].
  3. Confirm the target block is a task list item first (ListData.Typ==3) to avoid the earlier 'block is not a task list item' error.

Example fix

// before
fetchPost('/api/block/updateTaskListItemMarker', { id, marker: '[x]' })
// after
fetchPost('/api/block/updateTaskListItemMarker', { id, marker: 'x' })
Defensive patterns

Strategy: validation

Validate before calling

// Validate marker is exactly one char before calling the API
function validTaskMarker(m) {
  return typeof m === 'string' && m.length === 1 && m !== '[' && m !== ']';
}
if (!validTaskMarker(marker)) { throw new Error('marker must be a single non-bracket char'); }

Type guard

function isTaskMarker(m: unknown): m is string {
  return typeof m === 'string' && m.length === 1 && m !== '[' && m !== ']';
}

Try / catch

try {
  await fetchPost('/api/block/updateTaskListItemMarker', { id, marker });
} catch (e) {
  if (/marker length should be 1/.test(e.msg)) { /* fix marker to single char, retry */ }
  else { throw e; }
}

Prevention

When it happens

Trigger: Calling POST /api/block/updateTaskListItemMarker with {"id":"<task-item-id>", "marker":""} or {"marker":"[x]"} or {"marker":"done"}. The endpoint (kernel/api/block_op.go:95 updateTaskListItemMarker) parses `marker` from JSON and passes it to buildUpdatedTaskListItemBlockDOM (block_op.go:49), which asserts `len(marker)==1` at line 73.

Common situations: Plugin or automation code that sends the GFM task syntax `[ ]`/`[x]` as the marker instead of the bare status character. UI code that clears the field or passes the full checkbox text. Migrating from an API that accepted `[x]` to this one that expects `x`, ` `, or a custom glyph.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/845a1be9c204379e. Report an issue: GitHub.