tobi/qmd · warning · Error

handelize: path "${path}" has no valid filename content

Error message

handelize: path "${path}" has no valid filename content

What it means

After splitting the path and stripping the extension, the remaining filename contains no letters, numbers, symbols (\p{So}/\p{Sk}), or '$' — i.e. only punctuation like dots, dashes, underscores — so no valid handle can be produced.

Source

Thrown at src/store.ts:2375

    // Split the run into individual emoji and convert each to hex, dash-separated
    return [...run].filter(c => /\p{So}|\p{Sk}/u.test(c))
      .map(c => c.codePointAt(0)!.toString(16)).join('-');
  });
}

export function handelize(path: string): string {
  if (!path || path.trim() === '') {
    throw new Error('handelize: path cannot be empty');
  }

  // Allow route-style "$" filenames while still rejecting paths with no usable content.
  // Emoji (\p{So}) counts as valid content — they get converted to hex codepoints below.
  const segments = path.split('/').filter(Boolean);
  const lastSegment = segments[segments.length - 1] || '';
  const filenameWithoutExt = lastSegment.replace(/\.[^.]+$/, '');
  const hasValidContent = /[\p{L}\p{N}\p{So}\p{Sk}$]/u.test(filenameWithoutExt);
  if (!hasValidContent) {
    throw new Error(`handelize: path "${path}" has no valid filename content`);
  }

  const result = path
    .replace(/___/g, '/')       // Triple underscore becomes folder separator
    .split('/')
    .map((segment, idx, arr) => {
      const isLastSegment = idx === arr.length - 1;

      // Convert emoji to hex codepoints before cleaning
      segment = emojiToHex(segment);

      if (isLastSegment) {
        // For the filename (last segment), preserve the extension
        const extMatch = segment.match(/(\.[a-z0-9]+)$/i);
        const ext = extMatch ? extMatch[1] : '';
        const nameWithoutExt = ext ? segment.slice(0, -ext.length) : segment;

        const cleanedName = nameWithoutExt

View on GitHub (pinned to dbfd0b4736)

Solutions

  1. Skip such files during indexing (filter before handelize)
  2. Rename the file to include at least one letter/number
  3. Pre-check the basename with the same regex before calling

Example fix

// before
const h = handelize(p); // p = 'tmp/-.md'
// after
const VALID = /[\p{L}\p{N}\p{So}\p{Sk}$]/u;
const base = p.split('/').filter(Boolean).pop()?.replace(/\.[^.]+$/, '') ?? '';
const h = VALID.test(base) ? handelize(p) : null;
Defensive patterns

Strategy: validation

Validate before calling

const VALID = /[\p{L}\p{N}\p{So}\p{Sk}$]/u;
const base = p.split('/').filter(Boolean).pop()?.replace(/\.[^.]+$/, '') ?? '';
if (VALID.test(base)) handelize(p); else skip();

Type guard

const hasHandleContent = (p: string) => /[\p{L}\p{N}\p{So}\p{Sk}$]/u.test((p.split('/').filter(Boolean).pop() || '').replace(/\.[^.]+$/, ''));

Prevention

When it happens

Trigger: Calling handelize on a path whose basename is all punctuation, e.g. handelize('docs/-.md') or handelize('...') — the filenameWithoutExt fails the /[\p{L}\p{N}\p{So}\p{Sk}$]/u test.

Common situations: Temp or system files named '-', '...', or '._.' being indexed; glob patterns matching dotfiles without meaningful names; sanitization upstream stripping all alphanumerics.

Related errors


AI-assisted analysis of tobi/qmd@dbfd0b4736 (2026-08-28). Data as JSON: /api/errors/aece9b36e69b4a43. Report an issue: GitHub.