{"record":{"id":"2cf7e3047666a9d5","repo":"CherryHQ/cherry-studio","slug":"theme-contract-label-contains-duplicate-names","errorCode":null,"errorMessage":"[theme-contract] ${label} contains duplicate names","messagePattern":"\\[theme-contract\\] (.+?) contains duplicate names","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/scripts/validate-theme-contract.ts","lineNumber":108,"sourceCode":"  })\n}\n\nfunction extractImports(source: string): string[] {\n  return [...stripComments(source).matchAll(/@import\\s+([^;]+);/g)].map((match) => {\n    const importValue = match[1].trim()\n    const stringMatch = importValue.match(/^(['\"])([^'\"]+)\\1$/)\n    if (stringMatch) return stringMatch[2]\n\n    const urlMatch = importValue.match(/^url\\(\\s*(?:(['\"])([^'\"]+)\\1|([^'\")\\s][^)]*?))\\s*\\)$/)\n    if (urlMatch) return (urlMatch[2] ?? urlMatch[3]).trim()\n\n    throw new Error(`[theme-contract] unsupported @import syntax: ${importValue}`)\n  })\n}\n\nfunction assertUnique(label: string, values: readonly string[]): void {\n  if (new Set(values).size !== values.length) {\n    throw new Error(`[theme-contract] ${label} contains duplicate names`)\n  }\n}\n\nfunction assertSurfacePairs(\n  label: string,\n  pairs: ReadonlyArray<readonly [surface: string, foreground: string]>,\n  variableNames: Set<string>\n): void {\n  const surfaces = new Set<string>()\n\n  for (const [surface, foreground] of pairs) {\n    if (surface === foreground || surfaces.has(surface)) {\n      throw new Error(`[theme-contract] ${label} has an invalid or duplicate surface pair for ${surface}`)\n    }\n    if (!variableNames.has(surface) || !variableNames.has(foreground)) {\n      throw new Error(`[theme-contract] ${label} pair ${surface} / ${foreground} is outside its public contract`)\n    }\n    surfaces.add(surface)","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/packages/ui/scripts/validate-theme-contract.ts#L90-L126","documentation":"Thrown by the theme contract validator when a labeled list of token names contains duplicates. The assertUnique function checks that new Set(values).size === values.length for various token arrays (runtime theme inputs, Shadcn variables, product variables, Tailwind product colors, compatibility tokens). A duplicate means the same variable name appears twice in a source-of-truth token list, which would cause ambiguous resolution.","triggerScenarios":"A token constant array in packages/ui/scripts/theme-contract.ts (e.g., SHADCN_VARIABLE_TOKENS, CHERRY_PRODUCT_VARIABLE_TOKENS, RUNTIME_THEME_INPUT_TOKENS, or one of the COMPATIBILITY_*_TOKENS arrays) contains the same string twice. The validator calls assertUnique on each array at the start of validateThemeContractSources.","commonSituations":"A developer adds a new token to a constant array but it was already present (e.g., adding 'background' when it's already listed). Copy-paste error when extending the token lists. A merge that combined two branches each adding the same token. Refactoring that moved tokens between arrays without removing the original.","solutions":["Inspect the token constant array identified by the label in the error message (e.g., 'Shadcn variables', 'product variables') in packages/ui/scripts/theme-contract.ts.","Remove the duplicate entry so each name appears exactly once.","Run the validator to confirm: npx tsx packages/ui/scripts/validate-theme-contract.ts."],"exampleFix":"// before — packages/ui/scripts/theme-contract.ts\nexport const SHADCN_VARIABLE_TOKENS = [\n  'background',\n  'foreground',\n  'background',  // ← duplicate\n  'card'\n] as const\n\n// after — remove duplicate\nexport const SHADCN_VARIABLE_TOKENS = [\n  'background',\n  'foreground',\n  'card'\n] as const","handlingStrategy":"validation","validationCode":"// Check token arrays for duplicates before committing theme-contract.ts changes\nimport { SHADCN_VARIABLE_TOKENS, CHERRY_PRODUCT_VARIABLE_TOKENS, RUNTIME_THEME_INPUT_TOKENS } from './theme-contract'\n\nfunction assertUnique(label: string, values: readonly string[]): void {\n  if (new Set(values).size !== values.length) {\n    const dupes = values.filter((v, i) => values.indexOf(v) !== i)\n    throw new Error(`${label} has duplicates: ${dupes.join(', ')}`)\n  }\n}\n\nassertUnique('Shadcn variables', SHADCN_VARIABLE_TOKENS)\nassertUnique('product variables', CHERRY_PRODUCT_VARIABLE_TOKENS)\nassertUnique('runtime inputs', RUNTIME_THEME_INPUT_TOKENS)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When adding a token to an array in theme-contract.ts, search the array first to confirm it's not already present.","Run the theme contract validator after any change to token arrays.","Use alphabetical ordering within token arrays to make duplicates visually obvious.","Review token arrays during code review specifically for duplicate entries."],"tags":["theme-contract","build-validation","tokens","duplicates","configuration"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}