From da9d1c376dc863b9c75ab73627380ac0e1aaef31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Sto=CC=88ckl?= Date: Sun, 1 Feb 2026 00:14:40 +0100 Subject: [PATCH] fix: workaround Bun UTF-8 path corruption bug Replace Bun.file() async calls with Node.js fs sync methods to work around a Bun bug that corrupts UTF-8 file paths containing non-ASCII characters. Bug: Bun.file(filepath).stat() and Bun.file(filepath).text() internally mangle UTF-8 encoding, causing ENOENT errors with mojibake paths when accessing files in iCloud Drive and other locations. Changes: - src/qmd.ts: Use readFileSync instead of Bun.file().text() - src/qmd.ts: Use statSync instead of Bun.file().stat() for file metadata - src/store.ts: Use statSync for SQLite custom path detection --- src/qmd.ts | 9 +++++---- src/store.ts | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/qmd.ts b/src/qmd.ts index 29fd2d1e..2aabf34a 100755 --- a/src/qmd.ts +++ b/src/qmd.ts @@ -2,6 +2,7 @@ import { Database } from "bun:sqlite"; import { Glob, $ } from "bun"; import { parseArgs } from "util"; +import { readFileSync, statSync } from "fs"; import * as sqliteVec from "sqlite-vec"; import { getPwd, @@ -281,7 +282,7 @@ function showStatus(): void { // Index size let indexSize = 0; try { - const stat = Bun.file(dbPath).size; + const stat = statSync(dbPath).size; indexSize = stat; } catch { } @@ -1401,7 +1402,7 @@ async function indexFiles(pwd?: string, globPattern: string = DEFAULT_GLOB, coll const path = handelize(relativeFile); // Normalize path for token-friendliness seenPaths.add(path); - const content = await Bun.file(filepath).text(); + const content = readFileSync(filepath, "utf-8"); // Skip empty files - nothing useful to index if (!content.trim()) { @@ -1427,7 +1428,7 @@ async function indexFiles(pwd?: string, globPattern: string = DEFAULT_GLOB, coll } else { // Content changed - insert new content hash and update document insertContent(db, hash, content, now); - const stat = await Bun.file(filepath).stat(); + const stat = statSync(filepath); updateDocument(db, existing.id, title, hash, stat ? new Date(stat.mtime).toISOString() : now); updated++; @@ -1436,7 +1437,7 @@ async function indexFiles(pwd?: string, globPattern: string = DEFAULT_GLOB, coll // New document - insert content and document indexed++; insertContent(db, hash, content, now); - const stat = await Bun.file(filepath).stat(); + const stat = statSync(filepath); insertDocument(db, collectionName, path, title, hash, stat ? new Date(stat.birthtime).toISOString() : now, stat ? new Date(stat.mtime).toISOString() : now); diff --git a/src/store.ts b/src/store.ts index 41390008..e6ce34c2 100644 --- a/src/store.ts +++ b/src/store.ts @@ -13,7 +13,7 @@ import { Database } from "bun:sqlite"; import { Glob } from "bun"; -import { realpathSync } from "node:fs"; +import { realpathSync, statSync } from "node:fs"; import * as sqliteVec from "sqlite-vec"; import { LlamaCpp, @@ -427,7 +427,7 @@ function setSQLiteFromBrewPrefixEnv(): void { for (const candidate of candidates) { try { - if (Bun.file(candidate).size > 0) { + if (statSync(candidate).size > 0) { Database.setCustomSQLite(candidate); return; }