{"record":{"id":"851715cea58b0eed","repo":"larksuite/cli","slug":"embeddedskills-nil-spec-must-not-be-nil","errorCode":null,"errorMessage":"EmbeddedSkills(nil): spec must not be nil","messagePattern":"EmbeddedSkills\\(nil\\): spec must not be nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extension/platform/builder.go","lineNumber":167,"sourceCode":"\tcp.Identities = append([]Identity(nil), rule.Identities...)\n\tb.rules = append(b.rules, &cp)\n\treturn b\n}\n\n// EmbeddedSkills contributes a SkillsOverlay (see SkillsOverlay) customizing\n// the CLI's embedded skill content. It implies FailClosed: although skill\n// content is not a command-enforcement boundary, the overlay is a distribution\n// build-integrity declaration. Silently skipping it could republish host\n// defaults that the distribution explicitly removed or replaced.\n//\n// Calling FailOpen before EmbeddedSkills is allowed; EmbeddedSkills overrides\n// it to FailClosed, matching Restrict. Calling FailOpen afterward leaves an\n// invalid final state that Build rejects. A later FailClosed restores a valid\n// final state. A plugin owns at most one SkillsOverlay, so calling\n// EmbeddedSkills more than once is a build error.\nfunc (b *Builder) EmbeddedSkills(spec *SkillsOverlay) *Builder {\n\tif spec == nil {\n\t\tb.errs = append(b.errs, errors.New(\"EmbeddedSkills(nil): spec must not be nil\"))\n\t\treturn b\n\t}\n\tif b.skillsOverlay != nil {\n\t\tb.errs = append(b.errs, errors.New(\"EmbeddedSkills() called more than once; a plugin owns at most one SkillsOverlay\"))\n\t\treturn b\n\t}\n\tb.caps.FailurePolicy = FailClosed\n\tb.skillsOverlay = cloneSkillsOverlay(spec)\n\treturn b\n}\n\n// cloneSkillsOverlay snapshots the caller's spec so a later mutation of the\n// same *SkillsOverlay cannot alter the staged copy. Selection and remap slices\n// are copied; Overlay/Base are fs.FS handles retained by reference (an fs.FS is\n// a read-only view, not caller-mutable state).\nfunc cloneSkillsOverlay(spec *SkillsOverlay) *SkillsOverlay {\n\tcp := *spec\n\tcp.Allow = append([]string(nil), spec.Allow...)","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/extension/platform/builder.go#L149-L185","documentation":"EmbeddedSkills() was called with a nil *SkillsOverlay. The builder rejects nil specs up front and records the error for Build(). A nil overlay carries no skills to embed, so it is treated as a programming mistake rather than a no-op.","triggerScenarios":"Calling builder.EmbeddedSkills(nil), e.g. when the overlay is produced conditionally or loaded from a source that returned nil on failure.","commonSituations":"Skill overlay file missing or failed to parse so the loader returned nil; a struct field of type *SkillsOverlay left unset; refactor that made overlay construction conditional.","solutions":["Build a valid *SkillsOverlay (with at least the required skills entries) before calling EmbeddedSkills","Skip the EmbeddedSkills call if the plugin has no overlay to ship","Call Build() to surface all accumulated builder errors and fix the nil input"],"exampleFix":"// before\nvar overlay *SkillsOverlay\nb.EmbeddedSkills(overlay)\n\n// after\nif overlay != nil {\n    b = b.EmbeddedSkills(overlay)\n}","handlingStrategy":"validation","validationCode":"if spec == nil {\n    return nil, fmt.Errorf(\"cannot build plugin: skills overlay is nil\")\n}\nb := builder.EmbeddedSkills(spec)","typeGuard":"func hasOverlay(s *SkillsOverlay) bool { return s != nil }","tryCatchPattern":null,"preventionTips":["Load and validate the SkillsOverlay before building; fail fast if the loader returns nil","Treat nil overlay as 'no overlay' and omit the EmbeddedSkills call","Keep overlay loading and plugin building in one code path so nil cannot slip through"],"tags":["go","plugin-builder","nil-argument"],"backgroundTag":"nil-argument","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"}