actualbudget/actual · error

Invalid font-family value for

Error message

Invalid font-family value for "${property}": empty font name in comma-separated list.

What it means

validateFontFamilyValue splits the font-family value on commas and validates each name after stripping quotes. This error is thrown when one of the comma-separated entries is empty (e.g. a trailing comma or consecutive commas), meaning the font stack names no font at that position.

Solutions

  1. Remove the empty entry or dangling comma in the font stack.
  2. Ensure every comma-separated item names a font or a generic family.
  3. Reinstall the theme after correcting actual.css.

Example fix

// before
--font-ui: Inter, , sans-serif;
// after
--font-ui: Inter, sans-serif;
Defensive patterns

Strategy: validation

Validate before calling

function hasNoEmptyFontEntries(v) {
  return v.split(',').every(part => part.replace(/^["']|["']$/g, '').trim() !== '');
}
if (!hasNoEmptyFontEntries(value)) throw new Error('dangling comma in font stack');

Type guard

function isWellFormedFontList(v: string): boolean {
  return v.trim().split(',').every(p => p.replace(/['"]/g, '').trim() !== '');
}

Try / catch

try {
  await installTheme(css);
} catch (err) {
  if ((err as Error).message.includes('empty font name')) {
    // highlight the malformed font stack for the theme author
  } else throw err;
}

Prevention

When it happens

Trigger: A --font-* variable value like `--font-ui: Inter,, sans-serif;` or `--font-mono: 'Fira Code', ;` in the theme's actual.css — any entry that is empty after quote stripping triggers the throw.

Common situations: Theme author left a dangling comma after editing the font stack; string concatenation or templating in a theme generator produced ',,'; hand-editing removed a font name but not its comma.

Related errors


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

Appendix: source

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

 *   'Fira Code', monospace
 *   "My Theme Font", sans-serif
 */
function validateFontFamilyValue(value: string, property: string): void {
  const trimmed = value.trim();
  if (!trimmed) {
    throw new Error(
      `Invalid font-family value for "${property}": value must not be empty.`,
    );
  }

  // Split on commas, then validate each font name
  const families = trimmed.split(',');

  for (const raw of families) {
    const name = stripQuotes(raw);

    if (!name) {
      throw new Error(
        `Invalid font-family value for "${property}": empty font name in comma-separated list.`,
      );
    }

    // Reject anything that looks like a function call (url(), expression(), etc.)
    if (/\(/.test(name)) {
      throw new Error(
        `Invalid font-family value for "${property}": function calls are not allowed. Only font names are permitted.`,
      );
    }
  }
}

/** Only var(--custom-property-name) is allowed; no fallbacks. Variable name: -- then [a-zA-Z0-9_-]+ (no trailing dash). */
const VAR_ONLY_PATTERN = /^var\s*\(\s*(--[a-zA-Z0-9_-]+)\s*\)$/i;

function isValidSimpleVarValue(value: string): boolean {
  const m = value.trim().match(VAR_ONLY_PATTERN);

View on GitHub (pinned to d4334cb6e6)