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

  1. Send exactly one character: marker:'x' for checked, marker:' ' (single space) for unchecked
  2. Strip surrounding brackets/whitespace client-side before calling the API: marker = raw.replace(/[\[\]\s]/g, '') and validate length === 1
  3. Map boolean state to the marker character: state ? 'x' : ' '
  4. 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

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

View on GitHub (pinned to 9f775e8a12)