siyuan-note/siyuan · error

capability model name collision [%s]: %s and %s

Error message

capability model name collision [%s]: %s and %s

What it means

The capability set's add method rejects a registration whose internal model/tool name (registration.ModelName, the name exposed as the OpenAI function tool name) is already used by another capability. Unlike error 81 the ID differs; only the derived model name collides. The error names both conflicting capability IDs.

Source

Thrown at kernel/agent/capability.go:302

	sort.Slice(set.definitions, func(i, j int) bool {
		return set.definitions[i].Function.Name < set.definitions[j].Function.Name
	})
	return set, nil
}

func (set *capabilitySet) add(registration *capabilityRegistration) error {
	if set.registrations == nil {
		set.registrations = map[string]*capabilityRegistration{}
	}
	if set.ids == nil {
		set.ids = map[string]*capabilityRegistration{}
	}
	if previous := set.ids[registration.ID]; previous != nil {
		return fmt.Errorf("capability ID collision [%s]: %s and %s",
			registration.ID, previous.ModelName, registration.ModelName)
	}
	if previous := set.registrations[registration.ModelName]; previous != nil {
		return fmt.Errorf("capability model name collision [%s]: %s and %s",
			registration.ModelName, previous.ID, registration.ID)
	}
	set.ids[registration.ID] = registration
	set.registrations[registration.ModelName] = registration
	set.definitions = append(set.definitions, openai.Tool{
		Type: openai.ToolTypeFunction,
		Function: &openai.FunctionDefinition{
			Name:        registration.ModelName,
			Description: registration.Description,
			Parameters:  convertSchema(registration.InputSchema),
		},
	})
	return nil
}

func validFrontendCapabilityID(id string) bool {
	if len(id) > 512 {
		return false

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Compare the two capability IDs in the error message to find the clashing pair
  2. Change the new capability's ModelName (derived from its tool function name) to a unique value
  3. Rename the tool function name in the plugin/manifest so the derived model name differs
  4. Re-register only one of the two conflicting capabilities

Example fix

// before: both register ModelName "frontend_search"
// after
registration.ModelName = "frontend_search_v2"
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, c := range capabilities { if seen[c.ModelName] { return fmt.Errorf("duplicate model name %s", c.ModelName) }; seen[c.ModelName] = true }

Try / catch

if err := set.Add(reg); err != nil { if strings.Contains(err.Error(), "model name collision") { return fmt.Errorf("rename tool function for %s: %w", reg.ID, err) }; return err }

Prevention

When it happens

Trigger: Registering two capabilities with distinct IDs whose ModelName values normalize/derive to the same string, so set.registrations already contains that model name when add is called.

Common situations: Two plugins define tools with the same function name; a capability ID sanitizes (e.g. lowercased/truncated) to the same model name as an existing tool; plugin update renamed the ID but kept the function name.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/4e598abc7a260877. Report an issue: GitHub.