{"record":{"id":"0428ac0879818c03","repo":"actualbudget/actual","slug":"invalid-value-trimmedvalue-for-property-pr","errorCode":null,"errorMessage":"Invalid value \"${trimmedValue}\" for property \"${property}\". Only simple CSS values are allowed (colors, lengths, numbers, keywords, or var(--name)). Other functions, URLs, and complex constructs are not permitted.","messagePattern":"Invalid value \"(.+?)\" for property \"(.+?)\"\\. Only simple CSS values are allowed \\(colors, lengths, numbers, keywords, or var\\(--name\\)\\)\\. Other functions, URLs, and complex constructs are not permitted\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/style/customThemes.ts","lineNumber":209,"sourceCode":"\n  // 6. CSS keywords: common safe keywords\n  const keywordPattern =\n    /^(inherit|initial|unset|revert|transparent|none|auto|normal)$/i;\n\n  // Check if value matches any allowed pattern\n  if (\n    hexColorPattern.test(trimmedValue) ||\n    rgbRgbaPattern.test(trimmedValue) ||\n    hslHslaPattern.test(trimmedValue) ||\n    lengthPattern.test(trimmedValue) ||\n    numberPattern.test(trimmedValue) ||\n    keywordPattern.test(trimmedValue)\n  ) {\n    return; // Value is allowed\n  }\n\n  // If none of the allowlist patterns match, reject the value\n  throw new Error(\n    `Invalid value \"${trimmedValue}\" for property \"${property}\". Only simple CSS values are allowed (colors, lengths, numbers, keywords, or var(--name)). Other functions, URLs, and complex constructs are not permitted.`,\n  );\n}\n\n// ─── @font-face validation ──────────────────────────────────────────────────\n\n/** Maximum size of a single base64-encoded font (bytes of decoded data). 2 MB. */\nexport const MAX_FONT_FILE_SIZE = 2 * 1024 * 1024;\n\n/** Maximum total size of all embedded font data across all @font-face blocks. 10 MB. */\nexport const MAX_TOTAL_FONT_SIZE = 10 * 1024 * 1024;\n\n/** Per-font-file fetch timeout so a hung font host can't stall theme install. */\nconst FONT_FETCH_TIMEOUT_MS = 15_000;\n\n/**\n * Extract @font-face blocks from CSS. Returns the blocks and the remaining CSS.\n * Only matches top-level @font-face blocks (not nested inside other rules).","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/style/customThemes.ts#L191-L227","documentation":"validatePropertyValue allowlists values for CSS custom properties in custom themes: only colors, lengths, numbers, keywords, var(--name) references, and (for --font-*) plain font lists pass. Any other construct — function calls other than var(), URLs, complex expressions — throws this error naming the offending property and value.","triggerScenarios":"Installing a theme whose actual.css sets a :root variable to a disallowed value, e.g. `--color-bg: url(bg.png);`, `--shadow: calc(1px + 2px);`, or any value matching none of the allowlist patterns.","commonSituations":"Theme CSS copied from web apps that freely use calc()/clamp()/image-set() in variables; themes referencing external assets via url(); minified CSS with exotic constructs.","solutions":["Rewrite the value as a plain simple value: a hex/rgb color, a length, a number, or a keyword (e.g. precompute calc() results).","Reference another theme variable instead of a function: use var(--other-var) where dynamic indirection is needed.","Remove url() references — external assets are not allowed in theme CSS.","Check the variable name against supported theme properties and drop unsupported ones."],"exampleFix":"// before\n--color-bg: url(assets/background.png);\n// after\n--color-bg: #1a1a2e;","handlingStrategy":"validation","validationCode":"const SAFE = /^(#[0-9a-fA-F]{3,8}|[\\w.%+-]+|var\\(--[\\w-]+\\)|rgb|rgba|hsl|hsla|\\d+(\\.\\d+)?(px|rem|em|%)?)/;\n// pre-check each declaration value against simple-value patterns before install","typeGuard":"function isSimpleCssValue(v: string): boolean {\n  return !/[({;@]/.test(v) || /^var\\(--[\\w-]+\\)$/.test(v.trim());\n}","tryCatchPattern":"try {\n  await installTheme(css);\n} catch (err) {\n  const m = (err as Error).message.match(/Invalid value \"(.*)\" for property \"(.*)\"/);\n  if (m) {\n    // show property m[2] and value m[1] in the theme validation report\n  } else throw err;\n}","preventionTips":["Precompute calc()/clamp() results into static values when authoring themes.","Restrict theme variables to colors, lengths, numbers, keywords, and var() references.","Run the theme through Actual's installer validation before publishing."],"tags":["css","validation","allowlist","theme"],"backgroundTag":"css-value-validation-failed","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}