googleapis/mcp-toolbox · error

invalid project ID : must match

Error message

invalid project ID %q: must match %s

What it means

ValidateInstanceConnectionName splits a Cloud SQL connection name (project:region:instance) and checks each part against upstream GCP naming rules. The project segment must match ^[a-z][-a-z0-9]{4,28}[a-z0-9]$ (6-30 chars, lowercase, start with letter). This validation exists because these parts get interpolated into shell commands, JDBC URLs, and generated code, so metacharacters must be rejected.

Solutions

  1. Get the canonical project ID via `gcloud projects describe <name> --format='value(projectId)'` and use it in the connection name
  2. Fix the connection name string to form 'my-project:us-central1:my-instance' with a valid lowercase project ID
  3. Check that you didn't pass the project number or an environment-variable placeholder that didn't expand

Example fix

// before
ValidateInstanceConnectionName("123456789012:us-central1:my-db")
// after
ValidateInstanceConnectionName("my-project-id:us-central1:my-db")
Defensive patterns

Strategy: validation

Validate before calling

var projectIDRe = regexp.MustCompile(`^[a-z][-a-z0-9]{4,28}[a-z0-9]$`)
parts := strings.SplitN(connName, ":", 3)
if len(parts) != 3 || !projectIDRe.MatchString(parts[0]) {
    return fmt.Errorf("project segment %q of connection name is not a valid project ID", parts[0])
}

Type guard

func isValidProjectID(id string) bool {
    return regexp.MustCompile(`^[a-z][-a-z0-9]{4,28}[a-z0-9]$`).MatchString(id)
}

Try / catch

project, region, instance, err := cloudsqlconnect.ValidateInstanceConnectionName(connName)
if err != nil {
    return fmt.Errorf("connection name %q rejected: %w (expected form 'project:region:instance')", connName, err)
}

Prevention

When it happens

Trigger: Passing a connection name whose project segment is invalid: contains uppercase, underscores, is fewer than 6 characters, starts with a digit or hyphen, or exceeds 30 characters.

Common situations: Developer used the project NUMBER (e.g. "123456789012") instead of the project ID; used the display name (which may contain uppercase/spaces); typo'd or truncated the project ID.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/05880d44aabcc99c. Report an issue: GitHub.

Appendix: source

Thrown at internal/util/cloudsqlconnect/inputvalidate.go:48

//   - Cloud SQL instance IDs:     https://cloud.google.com/sql/docs/postgres/instance-settings
var (
	projectIDRe        = regexp.MustCompile(`^[a-z][-a-z0-9]{4,28}[a-z0-9]$`)
	gcpRegionRe        = regexp.MustCompile(`^[a-z]+-[a-z0-9-]+$`)
	cloudSQLInstanceRe = regexp.MustCompile(`^[a-z][a-z0-9-]{0,97}[a-z0-9]$`)
	gceResourceRe      = regexp.MustCompile(`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$`)
	databaseNameRe     = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_-]{0,62}$`)
)

// ValidateInstanceConnectionName splits and validates project, region, and
// instance ID per the GCP naming rules. Use this in place of plain
// ParseConnectionName when the parts will flow into generated code or shell.
func ValidateInstanceConnectionName(connName string) (project, region, instance string, err error) {
	project, region, instance, err = ParseConnectionName(connName)
	if err != nil {
		return "", "", "", err
	}
	if !projectIDRe.MatchString(project) {
		return "", "", "", fmt.Errorf("invalid project ID %q: must match %s", project, projectIDRe)
	}
	if !gcpRegionRe.MatchString(region) {
		return "", "", "", fmt.Errorf("invalid region %q: must match %s", region, gcpRegionRe)
	}
	if !cloudSQLInstanceRe.MatchString(instance) {
		return "", "", "", fmt.Errorf("invalid Cloud SQL instance ID %q: must match %s", instance, cloudSQLInstanceRe)
	}
	return project, region, instance, nil
}

// ValidateGCEResourceName checks a VM name or zone name against the standard
// GCE resource-name rule (lowercase, digits, hyphen; must start with a letter
// and not end with a hyphen, max 63 chars).
func ValidateGCEResourceName(name, kind string) error {
	if !gceResourceRe.MatchString(name) {
		return fmt.Errorf("invalid %s %q: must match %s", kind, name, gceResourceRe)
	}
	return nil

View on GitHub (pinned to 8cc6e09de2)