larksuite/cli · error
invalid plugin name %q: must match ^[a-z0-9][a-z0-9-]*$
Error message
invalid plugin name %q: must match ^[a-z0-9][a-z0-9-]*$
What it means
NewPlugin in extension/platform validates the plugin name against ^[a-z0-9][a-z0-9-]*$ and records this error on the Builder. The name must start with a lowercase letter or digit and contain only lowercase alphanumerics and hyphens.
Source
Thrown at extension/platform/builder.go:62
skillsOverlay *SkillsOverlay
hookNames map[string]bool
errs []error
}
var pluginNamePattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
// NewPlugin starts a Builder. Name format is validated lazily — errors
// surface at Build()/MustBuild() time, allowing chained calls without
// intermediate error handling.
func NewPlugin(name, version string) *Builder {
b := &Builder{
name: name,
version: version,
hookNames: map[string]bool{},
}
if !pluginNamePattern.MatchString(name) {
b.errs = append(b.errs, fmt.Errorf("invalid plugin name %q: must match ^[a-z0-9][a-z0-9-]*$", name))
}
return b
}
// RequireCLI sets Capabilities.RequiredCLIVersion (semver constraint,
// e.g. ">=1.1.0"). Empty string means no requirement.
func (b *Builder) RequireCLI(constraint string) *Builder {
b.caps.RequiredCLIVersion = constraint
return b
}
// FailOpen sets Capabilities.FailurePolicy = FailOpen. Default when
// neither FailOpen nor FailClosed is called and neither Restrict nor
// EmbeddedSkills is used. Build rejects a final FailOpen state after either
// safety-sensitive contribution.
func (b *Builder) FailOpen() *Builder {
b.caps.FailurePolicy = FailOpen
return bView on GitHub (pinned to 7fd6ef3c07)
Solutions
- Rename the plugin to lowercase kebab-case, e.g. "my-plugin"
- Normalize the name before calling NewPlugin: lowercase and replace '_'/' ' with '-'
- Check that the name does not start with '-' or contain consecutive invalid characters
- Read the error's %q value to see the exact offending string
Example fix
// before
b := platform.NewPlugin("My_Plugin", "1.0.0")
// after
b := platform.NewPlugin("my-plugin", "1.0.0") Defensive patterns
Strategy: validation
Validate before calling
var pluginNameRe = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
if !pluginNameRe.MatchString(name) { return fmt.Errorf("bad plugin name %q", name) } Try / catch
b := platform.NewPlugin(name, ver)
if len(b.Errs()) > 0 { /* inspect b.Errs() for the name error before building */ } Prevention
- Normalize names: strings.ToLower + replace non [a-z0-9-] with '-'
- Lint plugin manifests for name pattern in CI
- Never derive plugin names from Go identifiers directly
- Keep a single slugify helper for plugin and hook names
When it happens
Trigger: Calling NewPlugin with a name containing uppercase letters, underscores, spaces, or starting with a hyphen, e.g. NewPlugin("My_Plugin", "1.0.0").
Common situations: Porting plugin names from camelCase or snake_case conventions; names derived from directory or Go package names; typos or copied product names with spaces.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- %s %q: hookName must match ^[a-z0-9][a-z0-9-]*$
- %s %q: hookName already used in this plugin
- invalid identity %q: must be user|bot
- invalid risk %q: must be read|write|high-risk-write
- required skill %q declared by %q is not a valid skill name
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/d99862e0d1cf5985.
Report an issue: GitHub.