actualbudget/actual · error

Invalid property "${property}". Property name cannot be empt

Error message

Invalid property "${property}". Property name cannot be empty after "--".

What it means

After stripping the '--' prefix, the property must still have a non-empty name. validateRootContent checks property.substring(2) and throws when nothing remains. This is a distinct case from the '--' literal check and catches names like '---' or '-- ' (trailing whitespace trimmed) that slip past the startsWith('--') test.

Source

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

    }

    // Validate property name format
    // CSS custom property names must:
    // - Start with --
    // - Not be empty (not just --)
    // - Not end with a dash
    // - 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.`,
      );
    }

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Add a valid name after the dashes (letters, digits, underscore, dash), e.g. '---: x;' -> '--color-bg: x;'
  2. Fix the name-generation/sanitization code so it yields a non-empty identifier
  3. Delete the empty property declaration
  4. Pre-validate names with /^--[a-zA-Z0-9_-]+[a-zA-Z0-9_]$/

Example fix

// before
:root {
  ---: #fff;
}
// after
:root {
  --color-bg: #fff;
}
Defensive patterns

Strategy: validation

Validate before calling

function namesValidAfterPrefix(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) => /^--[a-zA-Z0-9_-]+\s*:/.test(d));
}

Type guard

const hasNameAfterDashes = (prop: string): boolean => prop.substring(2).length > 0;

Try / catch

try {
  const validated = validateThemeCss(generatedCss);
} catch (e) {
  if (e instanceof Error && e.message.includes('empty after "--"')) {
    showError('A variable name is missing after the -- prefix.');
  }
}

Prevention

When it happens

Trigger: Calling validateThemeCss with ':root { ---: x; }' or a property consisting only of dashes plus whitespace, or runtime-built names like '--' + suffix where suffix is empty after sanitization.

Common situations: Sanitization code stripping valid characters down to nothing, template strings where the name portion was filtered out, or typos with too many dashes.

Related errors


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