ruvnet/ruflo · error · Error

GCS not configured. Set GCS_BUCKET environment variable. Or

Error message

GCS not configured. Set GCS_BUCKET environment variable.
Or authenticate: gcloud auth login && gcloud config set project YOUR_PROJECT

What it means

uploadToGCS() starts from getGCSConfig(), which assembles configuration from the environment (GCS_BUCKET etc.). When that yields nothing — GCS_BUCKET unset and no explicit options.config — the function throws before doing any work, with the two recovery paths in the message: set GCS_BUCKET, or authenticate via gcloud. The upload itself shells out to `gcloud storage cp`, so both a bucket and a working gcloud login are required.

Source

Thrown at v3/@claude-flow/cli/src/transfer/storage/gcs.ts:111

  const hash = crypto.createHash('sha256').update(content).digest('hex');
  return `cfp-${hash.slice(0, 16)}`;
}

/**
 * Upload content to Google Cloud Storage using gcloud CLI
 */
export async function uploadToGCS(
  content: Buffer,
  options: {
    name?: string;
    contentType?: string;
    config?: GCSConfig;
    metadata?: Record<string, string>;
  } = {}
): Promise<GCSUploadResult> {
  const config = options.config || getGCSConfig();
  if (!config) {
    throw new Error(
      '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)) {

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. export GCS_BUCKET=your-bucket (plus project config via gcloud config set project YOUR_PROJECT) and rerun
  2. Authenticate once: gcloud auth login && gcloud config set project YOUR_PROJECT (the uploader invokes gcloud storage cp)
  3. Or pass explicit configuration programmatically via options.config (GCSConfig with bucket/prefix)
  4. Verify with `gcloud storage ls gs://your-bucket` that credentials and bucket both work before uploading

Example fix

# before
npx claude-flow hooks transfer store --storage gcs
# throws: GCS not configured. Set GCS_BUCKET...

# after
gcloud auth login && gcloud config set project my-project
export GCS_BUCKET=my-pattern-bucket
npx claude-flow hooks transfer store --storage gcs
Defensive patterns

Strategy: validation

Validate before calling

const bucket = process.env.GCS_BUCKET;
if (!bucket) {
  throw new Error('GCS storage selected but GCS_BUCKET is not set — configure it or choose another storage backend');
}
await uploadToGCS(content, { name });

Prevention

When it happens

Trigger: Calling uploadToGCS(content) with GCS_BUCKET unset in the process env; running in CI where the variable was never added to the job environment; passing no options.config while relying purely on ambient environment.

Common situations: Fresh machines that never ran gcloud auth login; env vars defined in .env but not loaded by the Node process; deploy pipelines that configure other providers (S3/web3) but not GCS.

Understand the failure class

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/5d9491530002d491. Report an issue: GitHub.