{"record":{"id":"cdc6ff841ecda5e5","repo":"kubernetes/kops","slug":"project-cannot-be-empty-specify-a-project-or-om","errorCode":null,"errorMessage":"--project cannot be empty; specify a project or omit the flag to use the gcloud default project","messagePattern":"--project cannot be empty; specify a project or omit the flag to use the gcloud default project","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops/create_cluster.go","lineNumber":935,"sourceCode":"\t\t\tfmt.Fprintf(&sb, \"Finally configure your cluster with: kops update cluster --name %s --yes --admin\\n\", cluster.Name)\n\t\t\tfmt.Fprintf(&sb, \"\\n\")\n\n\t\t\t_, err := out.Write(sb.Bytes())\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error writing to output: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// checkProjectFlag rejects an explicitly empty --project flag. An empty value usually comes from\n// an unset environment variable (e.g. --project=$PROJECT); silently accepting it would fall back\n// to the gcloud default project, which may not be the intended one.\nfunc checkProjectFlag(flagSet bool, project string) error {\n\tif flagSet && project == \"\" {\n\t\treturn fmt.Errorf(\"--project cannot be empty; specify a project or omit the flag to use the gcloud default project\")\n\t}\n\treturn nil\n}\n\n// parseCloudLabels takes a CSV list of key=value records and parses them into a map. Nested '='s are supported via\n// quoted strings (eg `foo=\"bar=baz\"` parses to map[string]string{\"foo\":\"bar=baz\"}. Nested commas are not supported.\nfunc parseCloudLabels(s string) (map[string]string, error) {\n\t// Replace commas with newlines to allow a single pass with csv.Reader.\n\t// We can't use csv.Reader for the initial split because it would see each key=value record as a single field\n\t// and significantly complicates using quoted fields as keys or values.\n\trecords := strings.ReplaceAll(s, \",\", \"\\n\")\n\n\t// Let the CSV library do the heavy-lifting in handling nested ='s\n\tr := csv.NewReader(strings.NewReader(records))\n\tr.Comma = '='\n\tr.FieldsPerRecord = 2\n\tr.LazyQuotes = false\n\tr.TrimLeadingSpace = true","sourceCodeStart":917,"sourceCodeEnd":953,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops/create_cluster.go#L917-L953","documentation":"checkProjectFlag rejects an explicitly-set but empty --project flag for the GCE provider. An empty value usually comes from --project=$PROJECT where the environment variable is unset, and silently falling back to the gcloud default project may target the wrong project. It is a pure input-validation error raised before any cloud calls.","triggerScenarios":"`kops create cluster --cloud gce --project=$PROJECT ...` where $PROJECT is unset/empty (flagSet=true, project=\"\"), hitting the guard at the top of checkProjectFlag.","commonSituations":"CI jobs missing the GCP project env export; copy-pasting commands referencing another machine's env; shell quoting swallowing the variable (single quotes around $PROJECT).","solutions":["Export the variable: export PROJECT=my-gcp-project before running kops.","Hardcode the project ID: --project my-gcp-project.","Or omit --project entirely to accept the gcloud default (verify with gcloud config get-value project).","Check the CI pipeline passes the project env var into the job."],"exampleFix":"// before\nkops create cluster --cloud gce --project=$PROJECT ...   # PROJECT unset\n// after\nexport PROJECT=my-gcp-project\nkops create cluster --cloud gce --project=$PROJECT ...","handlingStrategy":"validation","validationCode":"func guardProjectFlag(flagSet bool, project string) error {\n\tif flagSet && strings.TrimSpace(project) == \"\" {\n\t\treturn fmt.Errorf(\"--project was set but resolves to empty; check $PROJECT\")\n\t}\n\treturn nil\n}\n// call before invoking kops:\n// if err := guardProjectFlag(projectFlagPresent, os.Getenv(\"PROJECT\")); err != nil { ... }","typeGuard":"func hasProjectFlag(args []string) (bool, string) {\n\tfor i, a := range args {\n\t\tif a == \"--project\" && i+1 < len(args) {\n\t\t\treturn true, args[i+1]\n\t\t}\n\t\tif strings.HasPrefix(a, \"--project=\") {\n\t\t\treturn true, strings.TrimPrefix(a, \"--project=\")\n\t\t}\n\t}\n\treturn false, \"\"\n}","tryCatchPattern":null,"preventionTips":["Export the GCP project env var in shell profiles and CI jobs.","Default the flag in scripts: PROJECT=\"${PROJECT:-my-default-project}\".","Verify with gcloud config get-value project before relying on the gcloud default.","Use set -u in bash to fail fast on unset variables."],"tags":["cli","gce","env-var","flag-validation"],"backgroundTag":"empty-env-var","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}