{"record":{"id":"4bb7cdf71df84535","repo":"paperclipai/paperclip","slug":"invalid-paperclip-page-default-prefix-use-lowercase-path","errorCode":null,"errorMessage":"Invalid PAPERCLIP_PAGE_DEFAULT_PREFIX: use lowercase path segments without leading or trailing slashes","messagePattern":"Invalid PAPERCLIP_PAGE_DEFAULT_PREFIX: use lowercase path segments without leading or trailing slashes","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/publish-announcements.ts","lineNumber":13,"sourceCode":"#!/usr/bin/env -S node --import tsx\nimport { execFileSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { lstat, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ANNOUNCEMENT_ANIMATION_MAX_BYTES, ANNOUNCEMENT_IMAGE_MAX_BYTES, ANNOUNCEMENT_MANIFEST_MAX_BYTES, announcementIdSchema, announcementManifestSchema } from \"../packages/shared/src/announcements.js\";\n\nimport { validateAnnouncementAnimation } from \"../server/src/services/announcement-animation.js\";\n\nexport function announcementPublishPrefix(staging?: string, hostPrefix?: string) {\n  if (hostPrefix !== undefined && !/^[a-z0-9-]+(?:\\/[a-z0-9-]+)*$/.test(hostPrefix)) {\n    throw new Error(\"Invalid PAPERCLIP_PAGE_DEFAULT_PREFIX: use lowercase path segments without leading or trailing slashes\");\n  }\n  const prefix = staging === undefined ? \"announcements/v1\" : `announcements/staging/${announcementIdSchema.parse(staging)}/v1`;\n  return hostPrefix ? `${hostPrefix}/${prefix}` : prefix;\n}\n\nexport function parseAnnouncementPublishArgs(args: string[]) {\n  let sourceDirectory: string | undefined;\n  let staging: string | undefined;\n  let mode: \"publish\" | \"dry-run\" | undefined;\n  const usage = \"Usage: publish-announcements.ts [directory] [--staging name] [--dry-run | --publish]\";\n  for (let index = 0; index < args.length; index++) {\n    const arg = args[index];\n    if (arg === \"--publish\" || arg === \"--dry-run\") {\n      if (mode) throw new Error(usage);\n      mode = arg === \"--publish\" ? \"publish\" : \"dry-run\";\n    } else if (arg === \"--staging\") {\n      if (staging !== undefined || !args[index + 1]) throw new Error(usage);\n      staging = announcementIdSchema.parse(args[++index]);","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/scripts/publish-announcements.ts#L1-L31","documentation":"announcementPublishPrefix validates the optional PAPERCLIP_PAGE_DEFAULT_PREFIX host prefix against /^[a-z0-9-]+(?:\\/[a-z0-9-]+)*$/ — lowercase alphanumeric-and-hyphen segments separated by single slashes, with no leading or trailing slash. An invalid value throws this error before any publishing happens.","triggerScenarios":"Calling announcementPublishPrefix (or the publish-announcements CLI) with hostPrefix containing uppercase letters, underscores, dots, leading/trailing slashes, empty segments ('//'), or other characters outside [a-z0-9-].","commonSituations":"Setting PAPERCLIP_PAGE_DEFAULT_PREFIX='/announcements' or 'My/Prefix' in CI secrets or .env; copying a URL with scheme into the prefix; using a trailing slash out of habit.","solutions":["Rewrite the prefix as lowercase path segments, e.g. 'pages/team-a' instead of '/Pages/Team-A/'.","Remove leading and trailing slashes from the env value.","Replace invalid characters (underscores, dots, spaces) with hyphens.","Leave PAPERCLIP_PAGE_DEFAULT_PREFIX unset to use the default 'announcements/v1' prefix."],"exampleFix":"// before\nPAPERCLIP_PAGE_DEFAULT_PREFIX=/Announcements/\n// after\nPAPERCLIP_PAGE_DEFAULT_PREFIX=announcements","handlingStrategy":"validation","validationCode":"const prefix = process.env.PAPERCLIP_PAGE_DEFAULT_PREFIX;\nif (prefix !== undefined && !/^[a-z0-9-]+(?:\\/[a-z0-9-]+)*$/.test(prefix)) {\n  throw new Error(`Bad PAPERCLIP_PAGE_DEFAULT_PREFIX: ${prefix}`);\n}","typeGuard":"const isValidPrefix = (p) => p === undefined || /^[a-z0-9-]+(?:\\/[a-z0-9-]+)*$/.test(p);","tryCatchPattern":"try {\n  const prefix = announcementPublishPrefix(staging, hostPrefix);\n} catch (e) {\n  if (String(e.message).includes('PAPERCLIP_PAGE_DEFAULT_PREFIX')) {\n    console.error('Fix the env var: lowercase [a-z0-9-] segments, no leading/trailing slashes.');\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Validate the env var in CI before running publish jobs.","Never include slashes at the start/end of the prefix value.","Use only lowercase letters, digits, and hyphens; no underscores or dots.","Document the expected format next to the secret/variable definition."],"tags":["config","validation","env-var","path"],"backgroundTag":"invalid-env-var-value","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}