actualbudget/actual · error

Invalid font-family value for "${property}": empty font name

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.

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)

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.