router-for-me/CLIProxyAPI · error

missing required field id

Error message

missing required field id

What it means

validateManifestPluginID() rejects a direct-install manifest whose id is empty after trimming. The id is the plugin's configuration key and install identity, so it is mandatory.

Source

Thrown at internal/pluginstore/manifest.go:169

	for index, artifact := range artifacts {
		parsed, errParse := url.Parse(strings.TrimSpace(artifact.URL))
		if errParse != nil {
			return fmt.Errorf("artifacts[%d]: invalid artifact url", index)
		}
		if parsed.User != nil {
			return fmt.Errorf("artifacts[%d]: pinned artifact url must not contain credentials", index)
		}
		if parsed.RawQuery != "" || parsed.Fragment != "" {
			return fmt.Errorf("artifacts[%d]: pinned artifact url must not contain query or fragment", index)
		}
	}
	return nil
}

func validateManifestPluginID(id string) error {
	id = strings.TrimSpace(id)
	if id == "" {
		return fmt.Errorf("missing required field id")
	}
	if !validPluginID(id) {
		return fmt.Errorf("invalid plugin id %q", id)
	}
	return nil
}

func validateManifestSourceURL(sourceURL string) error {
	sourceURL = strings.TrimSpace(sourceURL)
	if sourceURL == "" {
		return fmt.Errorf("missing required field source-url")
	}
	parsed, errParse := url.Parse(sourceURL)
	if errParse != nil || parsed.Scheme == "" || parsed.Host == "" {
		return fmt.Errorf("invalid source-url")
	}
	if parsed.Scheme != "https" && parsed.Scheme != "http" {
		return fmt.Errorf("source-url must use http or https")

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Set id to a stable identifier, e.g. "acme.plugin"
  2. Confirm the manifest key is exactly id and maps to Manifest.ID
  3. Re-run Validate() — this error surfaces before the format checks in error 689, so fix emptiness first

Example fix

# before
id: ""   # or key misspelled as name:
# missing required field id

# after
id: acme.plugin
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(m.ID) == "" && m.InstallType() == pluginstore.InstallTypeDirect {
    return errors.New("manifest id required")
}
_ = m.Validate()

Type guard

func hasPluginID(m pluginstore.Manifest) bool { return strings.TrimSpace(m.ID) != "" }

Try / catch

if err := m.Validate(); err != nil && strings.Contains(err.Error(), "missing required field id") { /* set ID then re-validate */ }

Prevention

When it happens

Trigger: Direct-install Manifest with ID set to "", " ", or a value that trims to empty; commonly a YAML key mismatch (name: instead of id:) so the field never populates.

Common situations: Renaming manifest fields during a format migration; JSON unmarshaling into a different struct tag; generating manifests programmatically and forgetting to set the id.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/ce3a7621f3552bc0. Report an issue: GitHub.