{"record":{"id":"2c97df496072a775","repo":"tobi/qmd","slug":"handelize-path-path-resulted-in-empty-string","errorCode":null,"errorMessage":"handelize: path \"${path}\" resulted in empty string after processing","messagePattern":"handelize: path \"(.+?)\" resulted in empty string after processing","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/store.ts","lineNumber":2409,"sourceCode":"        const nameWithoutExt = ext ? segment.slice(0, -ext.length) : segment;\n\n        const cleanedName = nameWithoutExt\n          .replace(/[^\\p{L}\\p{N}$]+/gu, '-')  // Keep letters, numbers, \"$\"; dash-separate rest (including dots)\n          .replace(/^-+|-+$/g, ''); // Remove leading/trailing dashes\n\n        return cleanedName + ext;\n      } else {\n        // For directories, just clean normally\n        return segment\n          .replace(/[^\\p{L}\\p{N}$]+/gu, '-')\n          .replace(/^-+|-+$/g, '');\n      }\n    })\n    .filter(Boolean)\n    .join('/');\n\n  if (!result) {\n    throw new Error(`handelize: path \"${path}\" resulted in empty string after processing`);\n  }\n\n  return result;\n}\n\n/**\n * Search result extends DocumentResult with score and source info\n */\nexport type SearchResult = DocumentResult & {\n  score: number;              // Relevance score (0-1)\n  source: \"fts\" | \"vec\";      // Search source (full-text or vector)\n  chunkPos?: number;          // Character position of matching chunk (for vector search)\n};\n\n/**\n * Ranked result for RRF fusion (simplified, used internally)\n */\nexport type RankedResult = {","sourceCodeStart":2391,"sourceCodeEnd":2427,"githubUrl":"https://github.com/tobi/qmd/blob/dbfd0b4736aeaf761d1a16ca8e424f071df8feb9/src/store.ts#L2391-L2427","documentation":"handelize() ran to completion but normalization/mapping of every segment produced empty strings that filtered out, leaving an empty result. This is a late safety check indicating the transformation logic itself discarded all content.","triggerScenarios":"A path that passes the hasValidContent check but whose segments all become '' after the replacement pipeline (___ → /, per-segment transforms) and .filter(Boolean) removes them.","commonSituations":"Edge-case paths composed only of '$' route markers plus separators, or segments that the transform maps to empty; regression in segment transform rules after a code change.","solutions":["Inspect the exact path in the error message and adjust the transforms or skip the file","Add a fallback handle (e.g. hash of the path) when result is empty","Report upstream if a legitimately valid path triggers it"],"exampleFix":"// before\nreturn result; // throws if ''\n// after\nreturn result || `h-${createHash('sha1').update(path).digest('hex').slice(0, 12)}`;","handlingStrategy":"fallback","validationCode":"const h = hasHandleContent(p) ? handelize(p) : hashName(p);","typeGuard":null,"tryCatchPattern":"try { return handelize(p); } catch (e) { if (/empty string after processing/.test((e as Error).message)) return `h-${sha1(p).slice(0, 12)}`; throw e; }","preventionTips":["Use hash-based fallback handles for odd paths","Test handelize with unicode/punctuation edge cases","Skip exotic system files from indexing"],"tags":["path","filename","edge-case"],"backgroundTag":"invalid-filename","analyzedSha":"dbfd0b4736aeaf761d1a16ca8e424f071df8feb9","analyzedAt":"2026-08-28T18:07:46.628Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}