{"record":{"id":"777e75050e99c06a","repo":"nexu-io/open-design","slug":"invalid-design-system-id-designsystemid","errorCode":null,"errorMessage":"invalid design system id: ${designSystemId}","messagePattern":"invalid design system id: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/brands/index.ts","lineNumber":2166,"sourceCode":"  metadata: ProjectMetadata,\n  sourceDir: string,\n  targetPrefix: string,\n): Promise<void> {\n  for (const file of collectFiles(sourceDir)) {\n    const projectPath = toPosixPath(path.join(targetPrefix, file.rel));\n    await writeProjectFile(projectsRoot, projectId, projectPath, fs.readFileSync(file.abs), { overwrite: true }, metadata);\n  }\n}\n\nfunction syncBrandSystemToUserDesignSystem(\n  userDesignSystemsRoot: string,\n  designSystemId: string,\n  brandsRoot: string,\n  brandId: string,\n  designMd: string,\n): void {\n  const dir = userDesignSystemDir(userDesignSystemsRoot, designSystemId);\n  if (!dir) throw new Error(`invalid design system id: ${designSystemId}`);\n  const brandRoot = resolveBrandFile(brandsRoot, brandId, []);\n  if (!brandRoot) throw new Error(`invalid brand id: ${brandId}`);\n\n  fs.writeFileSync(path.join(dir, 'DESIGN.md'), designMd, 'utf8');\n  copyDirectorySync(brandSystemDir(brandsRoot, brandId), path.join(dir, 'system'));\n  copyOptionalDirectorySync(path.join(brandRoot, 'logos'), path.join(dir, 'logos'));\n  copyOptionalDirectorySync(path.join(brandRoot, 'fonts'), path.join(dir, 'fonts'));\n  copyOptionalDirectorySync(path.join(brandRoot, 'imagery'), path.join(dir, 'imagery'));\n  copyOptionalDirectorySync(path.join(brandRoot, 'prefetch'), path.join(dir, 'prefetch'));\n  const brandJson = resolveBrandFile(brandsRoot, brandId, ['brand.json']);\n  if (brandJson && isFile(brandJson)) {\n    fs.copyFileSync(brandJson, path.join(dir, 'brand.json'));\n  }\n}\n\nfunction userDesignSystemDir(root: string, id: string): string | null {\n  if (!id.startsWith('user:')) return null;\n  const dirId = id.slice('user:'.length);","sourceCodeStart":2148,"sourceCodeEnd":2184,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/brands/index.ts#L2148-L2184","documentation":"Thrown by syncBrandSystemToUserDesignSystem when userDesignSystemDir(root, designSystemId) returns null. The id must start with the literal prefix 'user:', the slug after the prefix must match /^[a-z0-9][a-z0-9-]*$/ (lowercase alphanumeric + hyphens, starting alphanumeric), AND the resolved path must stay inside root (path-containment guard). Built-in ids without the 'user:' prefix are rejected here.","triggerScenarios":"Passing a design-system id that omits the 'user:' prefix (e.g. a built-in id); an id with uppercase, underscores, dots, or slashes; an id whose resolved path escapes the user design systems root.","commonSituations":"Using a raw slug instead of the prefixed form; passing a built-in design-system id where a user one is required; constructing ids from untrusted input without the prefix or charset check.","solutions":["Prefix the id with 'user:' (e.g. 'user:my-brand').","Ensure the slug after the prefix is lowercase, starts with an alphanumeric, and uses only [a-z0-9-].","Reject ids with '/', '\\', '..', or uppercase before calling this function."],"exampleFix":"// before\nsyncBrandSystemToUserDesignSystem(root, 'My-Brand', brandsRoot, brandId, designMd); // missing user: prefix + uppercase -> throws\n\n// after\nsyncBrandSystemToUserDesignSystem(root, 'user:my-brand', brandsRoot, brandId, designMd);","handlingStrategy":"validation","validationCode":"function isUserDesignSystemId(id: string): boolean {\n  if (!id.startsWith('user:')) return false;\n  const slug = id.slice('user:'.length);\n  return /^[a-z0-9][a-z0-9-]*$/u.test(slug);\n}\nif (!isUserDesignSystemId(designSystemId)) {\n  throw new Error(`Design system id must start with 'user:' and use a lowercase kebab slug.`);\n}","typeGuard":"function isUserDesignSystemId(id: unknown): id is string {\n  return typeof id === 'string'\n    && id.startsWith('user:')\n    && /^[a-z0-9][a-z0-9-]*$/u.test(id.slice('user:'.length));\n}","tryCatchPattern":"try {\n  syncBrandSystemToUserDesignSystem(root, designSystemId, brandsRoot, brandId, designMd);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('invalid design system id:')) {\n    return badRequest(\"Design system id must be 'user:<lowercase-kebab-slug>'.\");\n  }\n  throw err;\n}","preventionTips":["Always prefix user design-system ids with 'user:'.","Lowercase and kebab-case the slug portion; only [a-z0-9-] are allowed after the first alphanumeric.","Reject ids with slashes, dots, underscores, or uppercase before calling the sync function."],"tags":["design-system","validation","path-traversal","security","brands"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}