How to Handle Errors During Browser-Based Conversions in the Convert Project
The convert project isolates errors at three distinct layers—handler initialization, per-step conversion, and overall conversion flow—using granular try/catch blocks, dead-end tracking, and user-facing alerts to ensure robust browser-based file conversion.
The p2r3/convert repository is a browser-based file conversion tool that processes media entirely client-side. When handling errors during browser-based conversions, the project implements a defensive architecture that prevents individual handler failures from crashing the entire application while providing clear feedback to users and developers.
Three-Layer Error Isolation Strategy
The error handling architecture operates at three distinct layers within src/main.ts, each protecting a specific phase of the conversion lifecycle.
Handler Initialization Layer
Before any conversion begins, the application attempts to initialize format handlers (such as ffmpeg or svgTrace) inside buildOptionList(). Errors during this phase are caught and silently handled to ensure the UI remains functional even if specific handlers fail to load.
// src/main.ts – building UI options, skipping handlers that fail to init
if (!window.supportedFormatCache.has(handler.name)) {
try {
await handler.init();
} catch (_) { continue; } // silently ignore init failures
}
When a handler fails initialization, it is simply skipped, and the dropdown menus only display formats from successfully loaded handlers.
Per-Step Conversion Layer
During the actual conversion process, each individual hop between formats is protected inside attemptConvertPath(). This function iterates through the conversion path and wraps every handler.doConvert() call in a dedicated try/catch block.
// src/main.ts – attempt each conversion hop
try {
files = (await Promise.all([
handler.doConvert(files, inputFormat, path[i + 1].format),
new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)))
]))[0];
if (files.some(c => !c.bytes.length)) throw "Output is empty.";
} catch (e) {
console.error(handler.name,
`${path[i].format.format} → ${path[i + 1].format.format}`, e);
deadEndAttempts.push(path.slice(0, i + 2));
window.traversionGraph.addDeadEndPath(path.slice(0, i + 2));
ui.popupBox.innerHTML = `<h2>Finding conversion route...</h2>
<p>Looking for a valid path...</p>`;
await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
return null; // try next candidate path
}
When a step fails, the error is logged to the console, the partial path is marked as a dead end in src/TraversionGraph.ts, and the UI updates to indicate it is searching for alternative routes. The function returns null, allowing the outer loop to attempt the next candidate path without crashing the application.
Overall Conversion Flow Layer
The highest level of protection wraps the entire user-initiated conversion process inside the ui.convertButton.onclick handler. This catch-all layer handles unexpected errors during file reading, route finding, or download preparation.
// src/main.ts – top‑level conversion click handler
ui.convertButton.onclick = async function () {
try {
// ... read files, show popup, call tryConvertByTraversing ...
} catch (e) {
window.hidePopup();
alert("Unexpected error while routing:\n" + e);
console.error(e);
}
};
If any unhandled exception bubbles up from the conversion logic, this layer hides any visible popup, displays a native browser alert with the error message, and logs the full stack trace to the console for debugging.
Dead-End Path Tracking and Route Optimization
Beyond simple error catching, the project implements intelligent failure tracking through src/TraversionGraph.ts. When attemptConvertPath() encounters a failing hop, it records the partial path in both a local deadEndAttempts array and the global traversionGraph instance via addDeadEndPath().
This mechanism prevents the routing algorithm from repeatedly attempting the same failing conversion sequences, significantly improving performance when searching for valid multi-step conversion paths between obscure formats.
User Feedback vs. Developer Diagnostics
The error handling strategy deliberately separates user-facing notifications from technical debugging information:
- User feedback appears through modal popups (updating to "Looking for a valid path…") and native
alert()dialogs for critical failures. This ensures users understand when the system is working on alternatives or when a conversion has definitively failed. - Developer diagnostics remain in the browser console through
console.error()andconsole.warn()calls, preserving stack traces and handler-specific error details without cluttering the user interface.
Individual handlers in src/handlers/*.ts (such as qoi-fu.ts and flptojson.ts) also implement internal try/catch blocks that convert thrown exceptions into rejected promises, ensuring consistent error propagation up to the main conversion loop.
Summary
- Three-layer isolation protects handler initialization, individual conversion steps, and the overall user flow through nested try/catch blocks in
src/main.ts. - Dead-end tracking via
src/TraversionGraph.tsprevents the routing algorithm from retrying failed conversion paths, optimizing search performance. - Graceful degradation ensures that failed handler initializations simply remove formats from the UI rather than crashing the application.
- Dual feedback channels separate user alerts from console diagnostics, providing clarity for end users while preserving technical details for developers.
Frequently Asked Questions
What happens if a format handler fails to initialize?
If a handler fails during initialization in buildOptionList(), the error is caught silently and that handler is skipped. The UI continues to populate with formats from successfully initialized handlers, ensuring the application remains functional even when specific conversion libraries fail to load.
How does the convert project prevent infinite loops when searching for conversion paths?
The project implements dead-end tracking through deadEndAttempts arrays and the traversionGraph.addDeadEndPath() method. When a conversion hop fails, that partial path is recorded and excluded from future route searches, preventing the algorithm from repeatedly attempting the same failing sequences.
Where are conversion errors logged for debugging?
Errors are logged to the browser console using console.error() at multiple layers: during handler initialization failures, within attemptConvertPath() when specific conversion steps fail, and in the top-level ui.convertButton.onclick handler for unexpected errors. This preserves stack traces and handler-specific details for developer debugging.
What user feedback appears when a conversion fails?
During the conversion process, users see modal popups that update from "Finding conversion route..." to "Looking for a valid path..." when errors occur. If all routes fail or an unexpected error bubbles up, the application displays a native browser alert with the message "Unexpected error while routing:" followed by the error details.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →