actualbudget/actual · error

Invalid property "${property}". Property name contains inval

Error message

Invalid property "${property}". Property name contains invalid characters. Only letters, digits, underscores, and dashes are allowed.

What it means

Custom property names in theme CSS may only contain letters, digits, underscores, and dashes after the '--' prefix. validateRootContent enforces this with the regex /^[a-zA-Z0-9_-]+$/ and rejects names containing spaces, brackets, dots, emoji, or other special characters, closing a CSS-injection surface.

Source

Thrown at packages/desktop-client/src/style/customThemes.ts:400

    // - Contain only valid characters (letters, digits, underscore, dash, but not at start/end positions)
    if (property === '--' || property === '-') {
      throw new Error(
        `Invalid property "${property}". Property name cannot be empty or contain only dashes.`,
      );
    }

    // Check for invalid characters in property name (no brackets, spaces, special chars except dash/underscore)
    // Property name after -- should only contain: letters, digits, underscore, and dashes (not consecutive dashes at start/end)
    const propertyNameAfterDashes = property.substring(2);
    if (propertyNameAfterDashes.length === 0) {
      throw new Error(
        `Invalid property "${property}". Property name cannot be empty after "--".`,
      );
    }

    // Check for invalid characters (no brackets, no special characters except underscore and dash)
    if (!/^[a-zA-Z0-9_-]+$/.test(propertyNameAfterDashes)) {
      throw new Error(
        `Invalid property "${property}". Property name contains invalid characters. Only letters, digits, underscores, and dashes are allowed.`,
      );
    }

    // Check that property doesn't end with a dash (after the -- prefix)
    if (property.endsWith('-')) {
      throw new Error(
        `Invalid property "${property}". Property name cannot end with a dash.`,
      );
    }

    // Extract and validate the value
    const value = decl.substring(colonIndex + 1).trim();
    validatePropertyValue(value, property);
  }
}

// ─── Main validation entry point ────────────────────────────────────────────

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Rename the property using only letters, digits, underscores, and dashes, e.g. '--my var' -> '--my-var'
  2. Escape-free rewrite: replace '.', '[', ']', spaces, etc. with '-' or '_' in the variable name
  3. Check the code that generates variable names and restrict it to /^[a-zA-Z0-9_-]+$/
  4. Remove the offending declaration if it is not needed

Example fix

// before
:root {
  --color[main]: red;
}
// after
:root {
  --color-main: red;
}
Defensive patterns

Strategy: validation

Validate before calling

const CUSTOM_PROP_NAME = /^--[a-zA-Z0-9_-]+[a-zA-Z0-9_]$/;
function namesAreSafe(css: string): boolean {
  const root = css.match(/:root\s*\{([\s\S]*?)\}/);
  if (!root) return false;
  return root[1]
    .split(';')
    .map((d) => d.trim())
    .filter(Boolean)
    .every((d) => CUSTOM_PROP_NAME.test(d.split(':')[0].trim()));
}

Type guard

const isValidPropName = (prop: string): boolean => /^--[a-zA-Z0-9_-]+$/.test(prop.substring(0, prop.indexOf(':')).trim());

Try / catch

try {
  const validated = validateThemeCss(userCss);
} catch (e) {
  if (e instanceof Error && e.message.includes('invalid characters')) {
    showError('Variable names may only use letters, digits, underscores, and dashes.');
  }
}

Prevention

When it happens

Trigger: Calling validateThemeCss with a property like '--color[main]: red;', '--my var: x;', '--font.size: 12px;', or any name with escaped/unicode/special characters inside :root.

Common situations: Copy-pasted CSS using hyphenated names with spaces, generated names containing dots or brackets, or themes ported from systems that allowed arbitrary variable names.

Understand the failure class

Related errors


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/924cb7999d4f7e91. Report an issue: GitHub.