{"record":{"id":"8d4388502d0dcc88","repo":"actualbudget/actual","slug":"invalid-property-property-property-name-cann","errorCode":null,"errorMessage":"Invalid property \"${property}\". Property name cannot be empty or contain only dashes.","messagePattern":"Invalid property \"(.+?)\"\\. Property name cannot be empty or contain only dashes\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/style/customThemes.ts","lineNumber":384,"sourceCode":"    }\n\n    const property = decl.substring(0, colonIndex).trim();\n\n    // Property must start with --\n    if (!property.startsWith('--')) {\n      throw new Error(\n        `Invalid property \"${property}\". Only CSS custom properties (starting with --) are allowed.`,\n      );\n    }\n\n    // Validate property name format\n    // CSS custom property names must:\n    // - Start with --\n    // - Not be empty (not just --)\n    // - Not end with a dash\n    // - Contain only valid characters (letters, digits, underscore, dash, but not at start/end positions)\n    if (property === '--' || property === '-') {\n      throw new Error(\n        `Invalid property \"${property}\". Property name cannot be empty or contain only dashes.`,\n      );\n    }\n\n    // Check for invalid characters in property name (no brackets, spaces, special chars except dash/underscore)\n    // Property name after -- should only contain: letters, digits, underscore, and dashes (not consecutive dashes at start/end)\n    const propertyNameAfterDashes = property.substring(2);\n    if (propertyNameAfterDashes.length === 0) {\n      throw new Error(\n        `Invalid property \"${property}\". Property name cannot be empty after \"--\".`,\n      );\n    }\n\n    // Check for invalid characters (no brackets, no special characters except underscore and dash)\n    if (!/^[a-zA-Z0-9_-]+$/.test(propertyNameAfterDashes)) {\n      throw new Error(\n        `Invalid property \"${property}\". Property name contains invalid characters. Only letters, digits, underscores, and dashes are allowed.`,\n      );","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/style/customThemes.ts#L366-L402","documentation":"A custom property name of just '--' (or a bare '-') is meaningless: after the required '--' prefix there is no name. validateRootContent explicitly rejects these degenerate names early with a dedicated message so users get a clearer hint than a generic character error.","triggerScenarios":"Calling validateThemeCss with ':root { --: red; }' or ':root { -- ; }' — typically from a broken template ('--${name}') where the variable name evaluated to an empty string, or from an accidental delete of the name.","commonSituations":"String interpolation building CSS at runtime with an undefined variable name, a search-and-replace that wiped names, or manual typo while editing theme CSS.","solutions":["Give the property a real name after the '--' prefix, e.g. '--: red;' -> '--color-accent: red;'","Check any code that builds the CSS string and ensure the interpolated variable name is defined and non-empty","Remove the empty declaration entirely if it is not needed","Guard template output: skip declarations whose generated name is empty"],"exampleFix":"// before\n:root {\n  --: red;\n}\n// after\n:root {\n  --color-accent: red;\n}","handlingStrategy":"validation","validationCode":"function namesAreNonEmpty(css: string): boolean {\n  const root = css.match(/:root\\s*\\{([\\s\\S]*?)\\}/);\n  if (!root) return false;\n  return root[1]\n    .split(';')\n    .map((d) => d.trim())\n    .filter(Boolean)\n    .every((d) => {\n      const name = d.split(':')[0].trim();\n      return name.length > 2;\n    });\n}","typeGuard":"const hasRealName = (prop: string): boolean => prop.length > 2;","tryCatchPattern":"try {\n  const validated = validateThemeCss(generatedCss);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('only dashes')) {\n    showError('A variable name is empty — check the code generating CSS variable names.');\n  }\n}","preventionTips":["Validate interpolated variable names before inserting into template strings","Never emit declarations whose generated name is empty","Sanitize names to /^[a-zA-Z0-9_-]+$/ before building CSS","Skip empty fragments when joining declarations"],"tags":["css","validation","custom-themes"],"backgroundTag":"invalid-css-custom-property","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}