ruvnet/ruflo · error · Error
GCS upload failed: ${error}
Error message
GCS upload failed: ${error} What it means
Thrown by uploadToGCS() in the pattern-transfer storage backend when the underlying `gcloud storage cp` subprocess (run via execFileSync) exits non-zero. The catch block unlinks the temp file and re-wraps the cause, so the message is an umbrella over every gcloud CLI failure: missing binary, expired credentials, nonexistent bucket, IAM denial, or network error. It only fires on the `cp` step; a failed metadata update is silently ignored because the upload itself succeeded.
Source
Thrown at v3/@claude-flow/cli/src/transfer/storage/gcs.ts:191
return {
success: true,
uri,
publicUrl,
size: content.length,
checksum,
contentId,
};
} catch (error) {
// Clean up temp file on error (validate path is within temp dir)
try {
const resolvedTemp = path.resolve(tempFile);
if (resolvedTemp.startsWith(path.resolve(tempDir))) {
fs.unlinkSync(tempFile);
}
} catch { /* ignore */ }
throw new Error(`GCS upload failed: ${error}`);
}
}
/**
* Download content from Google Cloud Storage
*/
export async function downloadFromGCS(
uri: string,
config?: GCSConfig
): Promise<Buffer | null> {
const cfg = config || getGCSConfig();
console.log(`[GCS] Downloading from ${uri}...`);
// Write to temp file first
const tempDir = process.env.TMPDIR || '/tmp';
const tempFile = path.join(tempDir, `claude-flow-download-${Date.now()}.json`);
View on GitHub (pinned to fa13ee4ad6)
Solutions
- Run `gcloud --version` on the machine doing the upload; if it fails, install the Google Cloud CLI and reopen the shell so it is on PATH.
- Authenticate and select a project: `gcloud auth login && gcloud config set project YOUR_PROJECT` (or set the project via the config used by uploadToGCS).
- Verify bucket access: `gcloud storage ls gs://YOUR-BUCKET` — fix the GCS_BUCKET value or grant the identity roles/storage.objectCreator on the bucket.
- Re-run the publish/transfer operation; if the failure is intermittent, wrap uploadToGCS in a retry with backoff.
Example fix
// before GCS_BUCKET=typo-bucket npx claude-flow hooks transfer publish // → Error: GCS upload failed: Error: Command failed: gcloud storage cp ... // after (terminal) gcloud auth login gcloud config set project my-project gcloud storage ls gs://my-patterns-bucket # proves credentials + bucket GCS_BUCKET=my-patterns-bucket npx claude-flow hooks transfer publish
Defensive patterns
Strategy: retry
Validate before calling
import { execFileSync } from 'node:child_process';
import { isGCloudAuthenticated } from './gcs.js';
function gcloudAvailable(): boolean {
try { execFileSync('gcloud', ['--version'], { stdio: 'pipe' }); return true; }
catch { return false; }
}
// call before uploading:
if (!gcloudAvailable()) throw new Error('install the gcloud CLI first');
if (!(await isGCloudAuthenticated())) throw new Error('run: gcloud auth login'); Try / catch
try {
const result = await uploadToGCS(content, { name, config });
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
if (!msg.startsWith('GCS upload failed:')) throw err; // not our error
if (/ENOENT/.test(msg)) throw new Error('gcloud CLI not installed');
if (/No project|quota|Unauthorized|401|403/.test(msg)) throw new Error(`auth/bucket perms: ${msg}`);
await backoffRetry(() => uploadToGCS(content, { name, config }), 3); // transient network
} Prevention
- Pre-flight gcloud --version and gcloud auth print-access-token in CI before any transfer command
- Pin GCS_BUCKET/GCS_PROJECT in the environment and verify with `gcloud storage ls gs://$GCS_BUCKET` during setup
- Treat metadata-update failures as non-fatal (the library already does) — only `cp` failures need handling
- Add retry-with-backoff only for messages matching network symptoms; retrying auth failures just burns quota
When it happens
Trigger: Calling uploadToGCS() (directly or via the publish/`hooks transfer` flow with the GCS backend) when: (1) the gcloud CLI is not installed (spawn ENOENT); (2) `gcloud auth login` was never run or the token expired; (3) GCS_BUCKET names a bucket that does not exist or the account lacks object-create permission; (4) config.projectId points at the wrong GCP project; (5) a transient network outage interrupts `gcloud storage cp`. Note: GCS_BUCKET being unset fails earlier with a distinct 'GCS not configured' error, so this message implies configuration was present but the upload operation itself failed.
Common situations: CI containers that never preinstalled the Cloud SDK; GCS_BUCKET exported on a laptop whose `gcloud config set project` was never set, so gcloud errors with 'No project found'; read-only service accounts; typo'd bucket names; corporate proxies blocking storage.googleapis.com.
Related errors
- GCS not configured. Set GCS_BUCKET environment variable. Or
- Invalid GCS bucket name: ${config.bucket}
- HTTP transport failed: ${firstError instanceof Error ? first
- Failed to fetch ${baseURL}/models: ${response.status} ${resp
- Resolved IP for ${hostname} is internal (${address})
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/8e78cd51946b4f41.
Report an issue: GitHub.