larksuite/cli · error · skillref.ErrInvalidRemap
%w: target %q: %w
Error message
%w: target %q: %w
What it means
resolveReferences could not parse the remap's target ('To') string into a skill reference; it wraps skillref.ErrInvalidRemap with the offending target and the parse error. Both endpoints of a remap must be canonical skill references.
Source
Thrown at internal/skillpolicy/resolver.go:137
content = composed
}
refs, err := resolveReferences(content, spec.ReferenceRemaps)
if err != nil {
return Resolution{}, fmt.Errorf("plugin %q skill spec: %w", owner, err)
}
return Resolution{Content: content, References: refs}, nil
}
func resolveReferences(content fs.FS, remaps []platform.SkillRefRemap) (*skillref.Resolver, error) {
mappings := make([]skillref.Mapping, 0, len(remaps))
for _, remap := range remaps {
from, err := skillref.Parse(remap.From())
if err != nil {
return nil, fmt.Errorf("%w: source %q: %w", skillref.ErrInvalidRemap, remap.From(), err)
}
to, err := skillref.Parse(remap.To())
if err != nil {
return nil, fmt.Errorf("%w: target %q: %w", skillref.ErrInvalidRemap, remap.To(), err)
}
mappings = append(mappings, skillref.Mapping{From: from, To: to})
}
return skillref.New(content, mappings)
}
// distinctOwners returns the unique contributing plugin names in
// first-seen order. Mirrors cmdpolicy.distinctOwners.
func distinctOwners(specs []PluginSkill) []string {
seen := map[string]bool{}
owners := make([]string, 0, len(specs))
for _, s := range specs {
if !seen[s.PluginName] {
seen[s.PluginName] = true
owners = append(owners, s.PluginName)
}
}
return ownersView on GitHub (pinned to 7fd6ef3c07)
Solutions
- Read the quoted target value and underlying parse error
- Correct To() to a valid canonical skill reference
- Add a unit test asserting skillref.Parse succeeds for every remap endpoint
- Ensure the target references a skill retained in the composed tree
Example fix
// before
platform.NewSkillRefRemap("deploy", "Release Guide")
// after
platform.NewSkillRefRemap("deploy", "release") Defensive patterns
Strategy: validation
Validate before calling
if _, err := skillref.Parse(remap.To()); err != nil {
return fmt.Errorf("invalid remap target %q: %w", remap.To(), err)
} Try / catch
_, err := skillpolicy.ResolveWithReferences(base, specs)
if errors.Is(err, skillref.ErrInvalidRemap) { /* fix To value */ } Prevention
- Run skillref.Parse on every To at plugin init
- Never use filesystem paths as remap targets
- Copy-edit remap pairs as a unit so From/To stay consistent
When it happens
Trigger: A ReferenceRemaps entry whose From() parses but whose To() fails skillref.Parse: empty target, invalid characters, or malformed path shape. Reached via ResolveWithReferences when remaps are configured.
Common situations: A remap destination typed as a filesystem path ('./guide.md') or containing typos/case errors, often after copying a From line and editing only partially.
Related errors
- %w: source %q: %w
- %w: source %q: %w
- invalid skill reference remap
- parse policy yaml: %w
- skill reference is empty
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/f3c8fa624484859f.
Report an issue: GitHub.