router-for-me/CLIProxyAPI · error

missing required field source-url

Error message

missing required field source-url

What it means

validateManifestSourceURL() rejects a direct-install manifest whose source-url is empty after trimming. Direct installs require a resolvable source link for provenance even though artifacts carry their own URLs.

Source

Thrown at internal/pluginstore/manifest.go:180

	}
	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")
	}
	if hasSensitiveQueryParameter(parsed) {
		return fmt.Errorf("source-url contains sensitive query parameter")
	}
	return nil
}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Add source-url: https://github.com/acme/plug to the manifest
  2. Check the exact key name is source-url and it unmarshals into Manifest.SourceURL
  3. Remember it must be a full http(s) URL with host, or errors 691/692 follow

Example fix

# before
version: 1.0.0
install: {type: direct}
# no source-url -> missing required field source-url

# after
version: 1.0.0
install: {type: direct}
source-url: https://github.com/acme/plug
Defensive patterns

Strategy: validation

Validate before calling

if m.InstallType() == pluginstore.InstallTypeDirect && strings.TrimSpace(m.SourceURL) == "" && len(pluginstore.NormalizeInstallPlan(m.Install).Artifacts) == 0 {
    return errors.New("source-url required for artifact-less direct install")
}
_ = m.Validate()

Type guard

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

Try / catch

if err := m.Validate(); err != nil && strings.Contains(err.Error(), "missing required field source-url") { /* set upstream https URL, re-validate */ }

Prevention

When it happens

Trigger: Direct-install Manifest with SourceURL unset, "", or whitespace; reaching here means the install plan had no artifacts branch (len(plan.Artifacts) == 0), so the source-url check is the final gate.

Common situations: Minimal test manifests omitting provenance; field name drift (source: vs source-url:); deleting the field while refactoring from github-release to direct installs.

Related errors


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