ruvnet/ruflo · error · Error
Invalid GCS bucket name: ${config.bucket}
Error message
Invalid GCS bucket name: ${config.bucket} What it means
Before invoking `gcloud storage cp`, uploadToGCS validates config.bucket through isValidBucketName(), which enforces GCS bucket naming rules (lowercase letters, digits, hyphens/underscores, length limits, no 'goog' prefix, etc.). A value failing those rules — uppercase letters, spaces, a 'gs://' scheme accidentally included, or a malformed name — is rejected. Comment 'S-1' marks this as command-injection hardening, since the bucket is interpolated into a gcloud argument.
Source
Thrown at v3/@claude-flow/cli/src/transfer/storage/gcs.ts:130
'GCS not configured. Set GCS_BUCKET environment variable.\n' +
'Or authenticate: gcloud auth login && gcloud config set project YOUR_PROJECT'
);
}
const contentId = generateContentId(content);
const checksum = crypto.createHash('sha256').update(content).digest('hex');
const fileName = options.name || `${contentId}.cfp.json`;
// Validate filename to prevent path traversal
if (!/^[a-zA-Z0-9._\-]+$/.test(fileName) || fileName.includes('..')) {
throw new Error(`Invalid filename: ${fileName}`);
}
const objectPath = config.prefix ? `${config.prefix}/${fileName}` : fileName;
// S-1: Validate bucket name and object path to prevent command injection
if (!isValidBucketName(config.bucket)) {
throw new Error(`Invalid GCS bucket name: ${config.bucket}`);
}
if (!isValidObjectPath(objectPath)) {
throw new Error(`Invalid GCS object path: ${objectPath}`);
}
console.log(`[GCS] Uploading to gs://${config.bucket}/${objectPath}...`);
// Write content to temp file
const tempDir = process.env.TMPDIR || '/tmp';
const tempFile = path.join(tempDir, `claude-flow-upload-${Date.now()}.json`);
fs.writeFileSync(tempFile, content);
try {
// Build gcloud args (array form prevents shell injection)
const uploadArgs = ['storage', 'cp', tempFile, `gs://${config.bucket}/${objectPath}`];
if (config.projectId) uploadArgs.push(`--project=${config.projectId}`);
uploadArgs.push(`--content-type=${options.contentType || 'application/json'}`);
View on GitHub (pinned to fa13ee4ad6)
Solutions
- Set GCS_BUCKET to the bare bucket name, lowercase, no scheme and no trailing slash — e.g. 'my-pattern-bucket' not 'gs://my-pattern-bucket/'
- Trim whitespace/newlines from the env value (common with .env files and shell exports)
- Rename to comply with GCS rules: 3-222 chars, lowercase letters/digits/hyphens/underscores, not starting with 'goog'
- Cross-check with `gcloud storage ls gs://<name>` that the name resolves before rerunning the upload
Example fix
# before export GCS_BUCKET="gs://My-Bucket/" # scheme + uppercase -> Invalid GCS bucket name # after export GCS_BUCKET=my-bucket npx claude-flow hooks transfer store --storage gcs
Defensive patterns
Strategy: validation
Validate before calling
function isValidBucketName(bucket: string): boolean {
return /^[a-z0-9][a-z0-9_-]{1,219}[a-z0-9]$/.test(bucket)
&& !bucket.startsWith('goog');
}
const bucket = process.env.GCS_BUCKET!;
if (!isValidBucketName(bucket)) {
throw new Error(`GCS_BUCKET '${bucket}' violates GCS naming rules (lowercase, no gs:// scheme, 3-222 chars)`);
}
await uploadToGCS(content, { config: { bucket } }); Prevention
- Store the bare bucket name — never 'gs://...' URIs or trailing slashes — in GCS_BUCKET
- Validate the env value at startup with a naming-rule regex rather than discovering it mid-upload
- GCS bucket names are lowercase-only; uppercase values always fail both this guard and GCS itself
When it happens
Trigger: Setting GCS_BUCKET='gs://my-bucket' (scheme included); uppercase or spaced bucket names like 'My Bucket'; trailing slashes; bucket names copied from URLs; values under 3 or over 222 characters.
Common situations: Pasting the bucket URI from the GCP console instead of the bare name; case mismatches (GCS buckets are globally lowercase-unique); whitespace from shell config or .env quoting; names with dots beyond allowed patterns.
Related errors
- GCS not configured. Set GCS_BUCKET environment variable. Or
- Invalid completion type
- Router multimodal is enabled but LLM_ROUTER_MULTIMODAL_MODEL
- Routes config must be a flat array of routes
- Invalid route entry: ${JSON.stringify(r)}
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/dcdde18a726bc4c3.
Report an issue: GitHub.