{"record":{"id":"839eee97afe88ccf","repo":"larksuite/cli","slug":"errinvalidhostbase","errorCode":"ErrInvalidHostBase","errorMessage":"%w: %w","messagePattern":"%w: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/skillpolicy/resolver.go","lineNumber":100,"sourceCode":"\t\trefs, err := skillref.New(base, nil)\n\t\tif err != nil {\n\t\t\treturn Resolution{}, err\n\t\t}\n\t\treturn Resolution{Content: base, References: refs}, nil\n\t}\n\n\towner, spec := specs[0].PluginName, specs[0].SkillsOverlay\n\tlower := base\n\tlowerLabel := \"host Base\"\n\tif spec.Base != nil {\n\t\tlower = protectPluginFS(owner, \"Base\", spec.Base)\n\t\tlowerLabel = \"plugin Base\"\n\t}\n\tupper := protectPluginFS(owner, \"Overlay\", spec.Overlay)\n\tlowerSnapshot, err := scanSkillTree(lowerLabel, lower)\n\tif err != nil {\n\t\tif spec.Base == nil {\n\t\t\treturn Resolution{}, fmt.Errorf(\"%w: %w\", ErrInvalidHostBase, err)\n\t\t}\n\t\treturn Resolution{}, fmt.Errorf(\"plugin %q skill spec: %w\", owner, err)\n\t}\n\tupperSnapshot, err := scanSkillTree(\"plugin Overlay\", upper)\n\tif err != nil {\n\t\treturn Resolution{}, fmt.Errorf(\"plugin %q skill spec: %w\", owner, err)\n\t}\n\tif err := validateSelection(lowerSnapshot, spec); err != nil {\n\t\treturn Resolution{}, fmt.Errorf(\"plugin %q skill spec: %w\", owner, err)\n\t}\n\tvar content fs.FS\n\tif lower == nil && upper == nil {\n\t\tcontent = nil\n\t} else {\n\t\tcomposed := newOverlayFS(lowerSnapshot, upperSnapshot, spec.Remove, spec.Allow)\n\t\tif err := validateRequiredSkills(composed); err != nil {\n\t\t\treturn Resolution{}, fmt.Errorf(\"plugin %q skill spec: %w\", owner, err)\n\t\t}","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/skillpolicy/resolver.go#L82-L118","documentation":"ErrInvalidHostBase reports that the wrapper-provided base skill tree (the CLI's embedded skill content, when the plugin did not supply its own Base) is malformed — unreadable root, non-directory entries, invalid skill names, or missing/invalid SKILL.md. It is kept distinct from plugin Base errors so diagnostics point at the host integrator, not the plugin.","triggerScenarios":"ResolveWithReferences is called with a spec whose Base is nil, and scanSkillTree on the host base fs.FS fails: fs.ReadDir on '.' errors, a top-level entry is not a directory, a name fails isSkillName, a skill lacks SKILL.md, or the manifest is invalid.","commonSituations":"An external wrapper main forgot to call cmd.SetEmbeddedSkillContent (or embedded an empty/mis-shaped tree) while a plugin requested Allow/Remove; the embedded FS layout was renamed; a build step that generates skill content silently produced the wrong structure.","solutions":["Check whether cmd.SetEmbeddedSkillContent was called with a valid embedded skill FS in the wrapper main.","Validate the base FS layout: every top-level entry must be a <skill>/ directory containing SKILL.md with valid metadata.","Unwrap the cause (errors.Is/errors.As) for the specific scan error (root unreadable, invalid name, missing SKILL.md).","If the plugin should own content, have it provide SkillsOverlay.Base so the host base is bypassed."],"exampleFix":"// before (wrapper main)\nfunc main() { cmd.Execute() } // never sets embedded skill content\n// after\nfunc main() {\n    cmd.SetEmbeddedSkillContent(skills.Embedded)\n    cmd.Execute()\n}","handlingStrategy":"validation","validationCode":"// verify the host base tree before calling the resolver\nentries, err := fs.ReadDir(hostBase, \".\")\nif err != nil { return fmt.Errorf(\"host base unreadable: %w\", err) }\nfor _, e := range entries {\n    if !e.IsDir() { return fmt.Errorf(\"%s is not a skill dir\", e.Name()) }\n    if _, err := fs.Stat(hostBase, e.Name()+\"/SKILL.md\"); err != nil {\n        return fmt.Errorf(\"skill %s missing SKILL.md: %w\", e.Name(), err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if errors.Is(err, skillpolicy.ErrInvalidHostBase) {\n        return fmt.Errorf(\"fix the wrapper's embedded skill content, not the plugin: %w\", err)\n    }\n    return err\n}","preventionTips":["Always call cmd.SetEmbeddedSkillContent with a valid embedded FS in wrapper mains.","Keep the embedded layout: <skill>/SKILL.md at top level only.","Run a startup self-check of the base tree in CI builds.","Distinguish host-base errors (ErrInvalidHostBase) from plugin errors when triaging."],"tags":["go","embedded-content","skills","host-integration"],"backgroundTag":"invalid-host-skill-base","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}