fix: remove console.error from graceful error handlers

Removed console.error calls from error handlers that gracefully skip
problematic files and continue processing. These handlers catch errors
when reading or parsing files but successfully return fallback values,
so logging errors creates unnecessary noise during testing and deployment.

Changes:
- vault-tools.ts: Remove console.error from search and frontmatter extraction
- search-utils.ts: Remove console.error from file search handlers
- waypoint-utils.ts: Remove console.error from file read handler
- frontmatter-utils.ts: Remove console.error from YAML and Excalidraw parsing

Test updates:
- Remove test assertions checking for console.error calls since these
  are no longer emitted by graceful error handlers

All 709 tests pass with no console noise during error handling.
This commit is contained in:
2025-10-26 12:44:00 -04:00
parent 8957f852b8
commit 48e429d59e
7 changed files with 19 additions and 72 deletions

View File

@@ -342,7 +342,6 @@ export class VaultTools {
}
} catch (error) {
// If frontmatter extraction fails, just return base metadata
console.error(`Failed to extract frontmatter for ${file.path}:`, error);
}
return baseMetadata;
@@ -685,7 +684,6 @@ export class VaultTools {
}
} catch (error) {
// Skip files that can't be read
console.error(`Failed to search file ${file.path}:`, error);
}
}

View File

@@ -64,7 +64,6 @@ export class FrontmatterUtils {
parsedFrontmatter = parseYaml(frontmatter) || {};
} catch (error) {
// If parsing fails, return null for parsed frontmatter
console.error('Failed to parse frontmatter:', error);
parsedFrontmatter = null;
}
@@ -318,7 +317,6 @@ export class FrontmatterUtils {
};
} catch (decompressError) {
// Decompression failed
console.error('Failed to process compressed Excalidraw data:', decompressError);
return {
isExcalidraw: true,
elementCount: 0,
@@ -350,10 +348,8 @@ export class FrontmatterUtils {
// If parsing fails, return with default values
const isExcalidraw = content.includes('excalidraw-plugin') ||
content.includes('"type":"excalidraw"');
// Log error for debugging
console.error('Excalidraw parsing error:', error);
return {
isExcalidraw: isExcalidraw,
elementCount: isExcalidraw ? 0 : undefined,

View File

@@ -116,7 +116,6 @@ export class SearchUtils {
}
} catch (error) {
// Skip files that can't be read
console.error(`Failed to search file ${file.path}:`, error);
}
}
@@ -325,7 +324,7 @@ export class SearchUtils {
}
}
} catch (error) {
console.error(`Failed to search waypoints in ${file.path}:`, error);
// Skip files that can't be searched
}
}

View File

@@ -102,7 +102,6 @@ export class WaypointUtils {
hasWaypoint = this.hasWaypointMarker(content);
} catch (error) {
// If we can't read the file, we can't check for waypoints
console.error(`Failed to read file ${file.path}:`, error);
}
// Determine result

View File

@@ -158,8 +158,7 @@ describe('FrontmatterUtils', () => {
describe('parse errors', () => {
test('handles parseYaml throwing error', () => {
const content = '---\ninvalid: yaml: content:\n---\nContent';
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
mockParseYaml.mockImplementation(() => {
mockParseYaml.mockImplementation(() => {
throw new Error('Invalid YAML');
});
@@ -169,13 +168,8 @@ describe('FrontmatterUtils', () => {
expect(result.frontmatter).toBe('invalid: yaml: content:');
expect(result.parsedFrontmatter).toBe(null);
expect(result.contentWithoutFrontmatter).toBe('Content');
expect(consoleErrorSpy).toHaveBeenCalledWith(
'Failed to parse frontmatter:',
expect.any(Error)
);
consoleErrorSpy.mockRestore();
});
});
test('handles parseYaml returning null', () => {
const content = '---\ntitle: Test\n---\nContent';
@@ -806,21 +800,15 @@ excalidraw-plugin`;
\`\`\`compressed-json
N4KAkARALgngDgUwgLgAQQQDwMYEMA2AlgCYBOuA7hADTgQBuCpAzoQPYB2KqATL
\`\`\``;
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
const result = FrontmatterUtils.parseExcalidrawMetadata(content);
expect(result.isExcalidraw).toBe(true);
expect(result.elementCount).toBe(0);
expect(result.hasCompressedData).toBe(true);
expect(result.metadata).toEqual({ compressed: true });
expect(consoleErrorSpy).toHaveBeenCalledWith(
'Failed to process compressed Excalidraw data:',
expect.anything()
);
consoleErrorSpy.mockRestore();
global.atob = originalAtob;
global.atob = originalAtob;
});
test('handles JSON parse error gracefully', () => {
@@ -828,28 +816,21 @@ N4KAkARALgngDgUwgLgAQQQDwMYEMA2AlgCYBOuA7hADTgQBuCpAzoQPYB2KqATL
\`\`\`json
{invalid json content}
\`\`\``;
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
const result = FrontmatterUtils.parseExcalidrawMetadata(content);
expect(result.isExcalidraw).toBe(true);
expect(result.elementCount).toBe(0);
expect(result.hasCompressedData).toBe(false);
expect(result.metadata).toEqual({});
expect(consoleErrorSpy).toHaveBeenCalledWith(
'Excalidraw parsing error:',
expect.any(Error)
);
consoleErrorSpy.mockRestore();
});
});
test('handles error when no Excalidraw marker present', () => {
const content = `\`\`\`json
{invalid json}
\`\`\``;
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
const result = FrontmatterUtils.parseExcalidrawMetadata(content);
expect(result.isExcalidraw).toBe(false);
@@ -857,21 +838,18 @@ N4KAkARALgngDgUwgLgAQQQDwMYEMA2AlgCYBOuA7hADTgQBuCpAzoQPYB2KqATL
expect(result.hasCompressedData).toBeUndefined();
expect(result.metadata).toBeUndefined();
consoleErrorSpy.mockRestore();
});
});
test('logs error but returns valid result structure', () => {
const content = 'excalidraw-plugin with error causing content';
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
// Force an error by making content throw during processing
const result = FrontmatterUtils.parseExcalidrawMetadata(content);
// Should still return valid structure
expect(result).toHaveProperty('isExcalidraw');
consoleErrorSpy.mockRestore();
});
});
});
describe('edge cases', () => {

View File

@@ -618,8 +618,7 @@ describe('SearchUtils', () => {
.mockResolvedValueOnce('test content')
});
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
const options: SearchOptions = {
query: 'test'
};
@@ -628,13 +627,8 @@ describe('SearchUtils', () => {
expect(result.stats.filesSearched).toBe(3);
expect(result.stats.filesWithMatches).toBe(2); // Only good files
expect(consoleErrorSpy).toHaveBeenCalledWith(
expect.stringContaining('Failed to search file bad.md'),
expect.any(Error)
);
consoleErrorSpy.mockRestore();
});
});
});
describe('statistics', () => {
@@ -1024,19 +1018,13 @@ Just some text
.mockRejectedValueOnce(new Error('Read error'))
});
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
const result = await SearchUtils.searchWaypoints(mockVault);
expect(result).toHaveLength(1);
expect(result[0].path).toBe('good.md');
expect(consoleErrorSpy).toHaveBeenCalledWith(
expect.stringContaining('Failed to search waypoints in bad.md'),
expect.any(Error)
);
consoleErrorSpy.mockRestore();
});
});
it('should continue searching after encountering errors', async () => {
const mockVault = createMockVaultAdapter({
@@ -1055,16 +1043,14 @@ Just some text
%% End Waypoint %%`)
});
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
const result = await SearchUtils.searchWaypoints(mockVault);
expect(result).toHaveLength(2);
expect(result[0].links).toEqual(['A']);
expect(result[1].links).toEqual(['B']);
consoleErrorSpy.mockRestore();
});
});
});
});
});

View File

@@ -296,19 +296,13 @@ Content without end`;
file.basename = 'Projects';
file.parent = folder;
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
(mockVault.read as jest.Mock).mockRejectedValue(new Error('Read failed'));
const result = await WaypointUtils.isFolderNote(mockVault, file);
expect(result.isFolderNote).toBe(true);
expect(result.reason).toBe('basename_match');
expect(consoleErrorSpy).toHaveBeenCalledWith(
expect.stringContaining('Failed to read file Projects/Projects.md'),
expect.any(Error)
);
consoleErrorSpy.mockRestore();
});
test('handles file read error - waypoint cannot be detected', async () => {
@@ -317,16 +311,13 @@ Content without end`;
file.basename = 'Index';
file.parent = folder;
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
(mockVault.read as jest.Mock).mockRejectedValue(new Error('Read failed'));
const result = await WaypointUtils.isFolderNote(mockVault, file);
expect(result.isFolderNote).toBe(false);
expect(result.reason).toBe('none');
expect(consoleErrorSpy).toHaveBeenCalled();
consoleErrorSpy.mockRestore();
});
test('handles unclosed waypoint as no waypoint', async () => {