{"record":{"id":"30d8e11971ab1fee","repo":"paperclipai/paperclip","slug":"set-paperclip-page-bucket-before-publishing","errorCode":null,"errorMessage":"Set PAPERCLIP_PAGE_BUCKET before publishing","messagePattern":"Set PAPERCLIP_PAGE_BUCKET before publishing","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/publish-announcements.ts","lineNumber":85,"sourceCode":"}\n\nexport function announcementUploadArgs(bucket: string, file: Awaited<ReturnType<typeof prepareAnnouncementPublish>>[\"files\"][number]) {\n  return [\"s3api\", \"put-object\", \"--bucket\", bucket, \"--key\", file.key, \"--body\", file.file,\n    \"--content-type\", file.contentType, \"--cache-control\", file.cacheControl];\n}\n\nasync function main() {\n  const { sourceDirectory, staging, publish } = parseAnnouncementPublishArgs(process.argv.slice(2));\n  const hostPrefix = process.env.PAPERCLIP_PAGE_DEFAULT_PREFIX;\n  const prepared = await prepareAnnouncementPublish(sourceDirectory, staging, hostPrefix);\n  const bucket = process.env.PAPERCLIP_PAGE_BUCKET;\n  const baseUrl = process.env.PAPERCLIP_PAGE_BASE_URL?.replace(/\\/+$/, \"\") ?? \"https://pages.paperclip.ing\";\n  const url = `${baseUrl}/${announcementPublishPrefix(staging, hostPrefix)}/current.json`;\n  const parsed = new URL(url);\n  if (parsed.protocol !== \"https:\" || parsed.username || parsed.password || parsed.search || parsed.hash) throw new Error(\"Invalid public base URL\");\n  console.log(JSON.stringify({ mode: publish ? \"publish\" : \"dry-run\", target: staging ? `staging/${staging}` : \"production\", bucket: bucket ?? \"(unset)\", url, announcementId: prepared.manifest.announcement?.id ?? null, files: prepared.files }, null, 2));\n  if (!publish) return;\n  if (!bucket) throw new Error(\"Set PAPERCLIP_PAGE_BUCKET before publishing\");\n  const env = { ...process.env };\n  const key = env.PAPERCLIP_PAGE_AWS_ACCESS_KEY_ID;\n  const secret = env.PAPERCLIP_PAGE_AWS_SECRET_ACCESS_KEY;\n  if (Boolean(key) !== Boolean(secret)) throw new Error(\"Set both namespaced page uploader credential variables\");\n  if (key && secret) {\n    env.AWS_ACCESS_KEY_ID = key;\n    env.AWS_SECRET_ACCESS_KEY = secret;\n    delete env.AWS_SESSION_TOKEN;\n    if (env.PAPERCLIP_PAGE_AWS_SESSION_TOKEN) env.AWS_SESSION_TOKEN = env.PAPERCLIP_PAGE_AWS_SESSION_TOKEN;\n  } else if (env.PAPERCLIP_PAGE_AWS_PROFILE) {\n    delete env.AWS_ACCESS_KEY_ID;\n    delete env.AWS_SECRET_ACCESS_KEY;\n    delete env.AWS_SESSION_TOKEN;\n    env.AWS_PROFILE = env.PAPERCLIP_PAGE_AWS_PROFILE;\n  }\n  // Only validated files, assets before manifest; credentials are scoped to AWS.\n  for (const file of prepared.files) execFileSync(\"aws\", announcementUploadArgs(bucket, file), { env, stdio: \"pipe\" });\n  console.log(\"Uploaded. Checking the public manifest (CDN propagation can take five minutes)…\");","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/scripts/publish-announcements.ts#L67-L103","documentation":"Actual S3 upload only happens when the script is run in publish mode (not dry-run), and it requires PAPERCLIP_PAGE_BUCKET to name the destination bucket. This error means publish mode was requested but the bucket variable is unset or empty.","triggerScenarios":"Running the script with the publish flag while PAPERCLIP_PAGE_BUCKET is not exported in the environment (CI job, shell without the export, wrong profile).","commonSituations":"Dry-run validation passes locally, then the publish run in CI lacks the env var because secrets weren't injected; switching machines or shells where the variable was defined only in a local .env.","solutions":["export PAPERCLIP_PAGE_BUCKET=<your-bucket-name> before running the script","Add PAPERCLIP_PAGE_BUCKET to your CI environment/secrets configuration","Re-run with publish mode omitted if you only wanted a dry-run","Verify with: printenv PAPERCLIP_PAGE_BUCKET"],"exampleFix":"// before\nnode scripts/publish-announcements.ts --publish  # no bucket set\n// after\nPAPERCLIP_PAGE_BUCKET=my-pages-bucket node scripts/publish-announcements.ts --publish","handlingStrategy":"validation","validationCode":"if (publish && !process.env.PAPERCLIP_PAGE_BUCKET) throw new Error(\"PAPERCLIP_PAGE_BUCKET is required for publish mode\");","typeGuard":null,"tryCatchPattern":"try { await main(); } catch (e) { if (e.message.startsWith(\"Set PAPERCLIP_PAGE_BUCKET\")) { /* export the bucket and retry */ } }","preventionTips":["Export PAPERCLIP_PAGE_BUCKET in your shell profile or CI secrets before publish runs","Do a dry-run first; only add --publish once env vars are confirmed","Check printenv PAPERCLIP_PAGE_BUCKET in the exact environment (CI job, container) that runs the script","Keep publish runs in CI where env vars are declared explicitly"],"tags":["env","config","announcements"],"backgroundTag":"missing-env-var","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}