siyuan-note/siyuan · error

tool handler is not configured

Error message

tool handler is not configured

What it means

The tool being invoked has neither a `ContextHandler` nor a `Handler` function set on its definition, so the dispatch at `server.go:296-301` falls through to the `else` branch. This is an internal registration defect: a tool was registered with `server.AddTool` but its `Tool` struct was not populated with a callable handler.

Source

Thrown at kernel/mcp/server.go:301

				if errors.Is(err, model.ErrEncryptedBoxNotUnlocked) {
					return toolErrorResult("encrypted notebook is locked, please unlock it first"), nil
				}
				logging.LogWarnf("mcp: acquire encrypted notebook operations for tool [%s] failed: %v", name, err)
				return toolErrorResult(err.Error()), nil
			}
		}
		defer releaseBoxLeases()

		var (
			result tools.CallToolResult
			err    error
		)
		if tool.ContextHandler != nil {
			result, err = tool.ContextHandler(ctx, arguments)
		} else if tool.Handler != nil {
			result, err = tool.Handler(arguments)
		} else {
			err = fmt.Errorf("tool handler is not configured")
		}
		if err != nil {
			return toolErrorResult(err.Error()), nil
		}
		if err = validator.ValidateOutputContext(ctx, result); err != nil {
			return toolErrorResult(fmt.Sprintf(
				"invalid tool output after execution; execution result may have side effects and must not be retried automatically: %v",
				err)), nil
		}

		content := make([]mcpsdk.Content, 0, len(result.Content))
		for _, item := range result.Content {
			converted, convertErr := convertContentItem(item)
			if convertErr != nil {
				return toolErrorResult(fmt.Sprintf(
					"invalid tool content after execution; execution result may have side effects and must not be retried automatically: %v",
					convertErr)), nil
			}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Locate the tool registration in `kernel/mcp/tools/*.go` and confirm the `Handler` (or `ContextHandler`) field is assigned.
  2. Rebuild/restart the kernel after fixing the registration so the corrected tool table is loaded.
  3. Add a unit test that asserts every registered tool has at least one handler set.

Example fix

// before
tools.Tool{Name: "foo", InputSchema: sch}
// after
tools.Tool{Name: "foo", InputSchema: sch, Handler: fooHandler}
Defensive patterns

Strategy: validation

Validate before calling

// Registry self-check: every registered tool must define a handler.
for _, t := range registeredTools {
    if t.Handler == nil && t.ContextHandler == nil {
        panic(fmt.Sprintf("tool %q has no handler configured", t.Name))
    }
}

Prevention

When it happens

Trigger: Calling any MCP tool whose `Tool` definition omitted both `Handler` and `ContextHandler`. Always reproducible for that tool name — it is a code/registration bug, not a runtime/transient condition.

Common situations: A tool was added to the registry with only metadata (name, schema) but its handler wiring was forgotten during refactoring. A conditional registration path that skips handler assignment under a feature flag.

Related errors


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