siyuan-note/siyuan · error

unsupported block operation

Error message

unsupported block operation [%s]

What it means

PerformBlockOperation returns "unsupported block operation [%s]" when the operation's Action falls into the default case of its switch — i.e. an action name the kernel does not implement. Only explicitly supported actions (such as "delete") reach the transaction stage.

Solutions

  1. Use exactly the supported action name (e.g. "delete" — lowercase, no variants).
  2. Check the server's API docs / handler source for the list of supported actions for your kernel version.
  3. Update the plugin/API client if it targets a different SiYuan version's action set.
  4. Validate the action string against a whitelist before sending.

Example fix

// before
await fetchPost('/api/block/performBlockOperation', { operations: [{ action: 'remove', id }] });
// after
await fetchPost('/api/block/performBlockOperation', { operations: [{ action: 'delete', id }] });
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED_ACTIONS = ['delete'];
function assertSupportedAction(action) {
  if (!SUPPORTED_ACTIONS.includes(action)) throw new Error(`unsupported action: ${action}`);
}

Try / catch

try { await performBlockOperation(action, id); } catch (e) { if (String(e.msg).includes('unsupported block operation')) console.error(`bad action '${action}'; see API docs for supported values`); throw e; }

Prevention

When it happens

Trigger: Passing an Action string that is not one of the supported values to the block operation API — typos like "Delete", "remove", or actions copied from another API's vocabulary.

Common situations: Plugin/API clients written against a newer or different API spec; hand-written automation scripts guessing action names; version drift where a client expects an action this kernel build does not support.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/9461f7bb6c78ea4d. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/block_operation.go:52

			if err = treenode.CheckContainerParent(operation.ParentID); err != nil {
				return nil, err
			}
		}
	case "delete":
		// 外部删除请求必须命中现存节点,编辑器内部仍可使用幂等删除。
		tree, loadErr := LoadTreeByBlockID(operation.ID)
		if loadErr != nil {
			return nil, loadErr
		}
		node := treenode.GetNodeInTree(tree, operation.ID)
		if node == nil {
			return nil, fmt.Errorf("block not found [%s]", operation.ID)
		}
		if node == tree.Root {
			return nil, fmt.Errorf("document cannot be deleted as a block [%s]", operation.ID)
		}
	default:
		return nil, fmt.Errorf("unsupported block operation [%s]", operation.Action)
	}

	tx := &Transaction{DoOperations: []*Operation{operation}}
	if err = performTxSyncLocked(tx); err != nil {
		return nil, err
	}
	return []*Transaction{tx}, nil
}

View on GitHub (pinned to 9f775e8a12)