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 falseView on GitHub (pinned to 8641553a1f)
Solutions
- Compare the two capability IDs in the error message to find the clashing pair
- Change the new capability's ModelName (derived from its tool function name) to a unique value
- Rename the tool function name in the plugin/manifest so the derived model name differs
- 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
- Keep tool function names globally unique across all plugins
- Derive ModelName from the namespaced capability ID so collisions are impossible
- Log all registered model names at startup to spot near-duplicates early
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
- capability ID collision [%s]: %s and %s
- invalid frontend capability [%s]: %w
- capability was not exposed in this model round
- host has no public IP:
- Failed to save agent session
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4e598abc7a260877.
Report an issue: GitHub.