From 4249952f0a4c063ed89a6dc0b9e28ec6812a2d58 Mon Sep 17 00:00:00 2001 From: afiqzudinhadi Date: Wed, 5 Aug 2026 15:34:50 +0800 Subject: [PATCH] fix(library): isolate per-note failures in candidate picker loop --- .../obsidian/src/library/LibraryController.ts | 14 +++++++--- tests/library-controller-isolation.test.ts | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 tests/library-controller-isolation.test.ts diff --git a/packages/obsidian/src/library/LibraryController.ts b/packages/obsidian/src/library/LibraryController.ts index 528d9c2..bfd2471 100644 --- a/packages/obsidian/src/library/LibraryController.ts +++ b/packages/obsidian/src/library/LibraryController.ts @@ -233,10 +233,16 @@ export class LibraryController { skipped++; continue; } - const content = await deps.readNote(entry.path); - await deps.writeNote(entry.path, patchFrontmatter(content, candidate.patches, { defaultType: spec.itemType })); - report.resolved.push(entry.path); - picked++; + try { + const content = await deps.readNote(entry.path); + await deps.writeNote(entry.path, patchFrontmatter(content, candidate.patches, { defaultType: spec.itemType })); + report.resolved.push(entry.path); + picked++; + } catch (e) { + const msg = e instanceof Error ? e.message : String(e); + console.log(`[media-db-library] picker failed for ${entry.filename}: ${msg}`); + skipped++; + } } } diff --git a/tests/library-controller-isolation.test.ts b/tests/library-controller-isolation.test.ts new file mode 100644 index 0000000..d2c235f --- /dev/null +++ b/tests/library-controller-isolation.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, test } from 'bun:test'; + +// Test that verifies the try/catch wrapping is syntactically correct +// and the error handling path exists in LibraryController.resolveType + +describe('LibraryController per-entry error isolation', () => { + test('try/catch present in resolveType for per-entry failures', async () => { + // Read the source file and verify try/catch is present + const srcText = (await Bun.file('packages/obsidian/src/library/LibraryController.ts').text()); + + // Verify the fix is in place: try block wrapping readNote/writeNote + expect(srcText).toContain('try {'); + expect(srcText).toContain('const content = await deps.readNote(entry.path);'); + expect(srcText).toContain('await deps.writeNote(entry.path'); + expect(srcText).toContain('} catch (e) {'); + expect(srcText).toContain('picker failed for'); + expect(srcText).toContain('skipped++;'); + }); + + test('error logging includes filename and message', async () => { + const srcText = await Bun.file('packages/obsidian/src/library/LibraryController.ts').text(); + + // Verify error log includes entry filename + expect(srcText).toContain('picker failed for ${entry.filename}'); + // Verify error message is captured + expect(srcText).toContain('e instanceof Error ? e.message : String(e)'); + }); +});