adam-p/markdown-here · error · Error
Error fetching local file: ${url}: ${err}
Error message
Error fetching local file: ${url}: ${err} What it means
The .catch at the end of getLocalFile's fetch chain re-throws every failure as `Error fetching local file: <url>: <err>`, wrapping the underlying cause (a network failure, the HTTP-status error from error [2], an unknown dataType, or a response.json() parse failure). Crucially, getLocalFile does not return the promise and its callback signature has no error parameter, so this throw is not catchable by the caller directly — it becomes an unhandled promise rejection. Note also that error[2] is always re-wrapped here, so callers effectively see this message rather than the raw HTTP-status one.
Source
Thrown at src/common/utils.js:330
throw new Error(`Unknown dataType: ${dataType}`);
}
})
.then(data => {
switch (dataType) {
case 'text':
case 'json':
callback(data);
break;
case 'base64':
data.arrayBuffer().then(function(buffer) {
var uInt8Array = new Uint8Array(buffer);
var base64Data = base64EncArr(uInt8Array);
callback(base64Data);
});
}
})
.catch(err => {
throw new Error(`Error fetching local file: ${url}: ${err}`);
});
}
// Events fired by Markdown Here will have this property set to true.
var MARKDOWN_HERE_EVENT = 'markdown-here-event';
// Fire a mouse event on the given element. (Note: not super robust.)
function fireMouseClick(elem) {
var clickEvent = elem.ownerDocument.createEvent('MouseEvent');
clickEvent.initMouseEvent(
'click',
true, // bubbles: We want the event to bubble.
true, // cancelable
elem.ownerDocument.defaultView, // view,
1, // detail,
0, // screenX
0, // screenYView on GitHub (pinned to e00d005299)
Solutions
- Validate url and dataType before calling, and confirm the resource exists and is fetchable from the current context (see error[2] fixes).
- Treat getLocalFile as fallible: refactor it to return the promise (per the TODO) so the caller can .catch the rejection instead of relying on the global unhandledrejection handler.
- Add a global unhandledrejection listener during development to surface these throws, since the callback contract gives no error channel.
- For json files, pre-validate that the file is non-empty and parses, or switch the dataType to 'text' and JSON.parse in the callback where you can try/catch.
Example fix
// before — errors vanish into an unhandled rejection (callback has no err arg)
getLocalFile(url, 'json', data => render(data));
// after — return the promise so callers can handle failure
function getLocalFile(url, dataType) {
return fetch(url).then(response => {
if (!response.ok) throw new Error(`HTTP error status: ${response.status}`);
if (dataType === 'text') return response.text();
if (dataType === 'json') return response.json();
if (dataType === 'base64') return response.blob();
throw new Error(`Unknown dataType: ${dataType}`);
});
}
// caller
getLocalFile(url, 'json').then(render).catch(err => console.error('load failed', err)); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate inputs before calling; this prevents the 'Unknown dataType' branch
// and reduces needless fetches for obviously bad URLs.
function validateGetLocalFileArgs(url, dataType) {
if (typeof url !== 'string' || url.length === 0) {
throw new Error('getLocalFile: url must be a non-empty string');
}
if (!['text', 'json', 'base64'].includes(dataType)) {
throw new Error(`getLocalFile: dataType must be text|json|base64, got ${dataType}`);
}
} Type guard
function isValidLocalFileDataType(dataType) {
return dataType === 'text' || dataType === 'json' || dataType === 'base64';
} Try / catch
// Because getLocalFile throws inside its internal .catch and returns nothing,
// the rejection is unhandled. Catch it at the process/window boundary and/or
// refactor to return the promise:
if (typeof window !== 'undefined') {
window.addEventListener('unhandledrejection', evt => {
if (evt.reason && /Error fetching local file/.test(evt.reason.message)) {
console.error('local file load failed:', evt.reason);
evt.preventDefault(); // mark handled
}
});
}
// Best fix: change getLocalFile to `return fetch(url)...` so the caller can
// `.catch(err => handleLocalFileError(url, err))` directly. Prevention
- Do not assume getLocalFile succeeds — its callback has no error channel and rejections currently escape as unhandled.
- Add a global unhandledrejection listener during development to surface these wrapped errors.
- Pre-validate dataType against text|json|base64 to avoid the Unknown dataType throw.
- Refactor getLocalFile to return its promise (the code's own TODO) so failures are catchable at the call site.
When it happens
Trigger: fetch() rejects (network error, blocked by CSP, missing host/extension permissions, CORS in a non-extension context); a non-2xx response triggers error[2] which is then caught and re-wrapped here; response.json() throws on malformed JSON; response.blob()/arrayBuffer() fails; an unsupported dataType is passed.
Common situations: Extension missing host_permissions for the URL; CSP blocking the request; corrupt or empty 'json' file; calling getLocalFile outside the extension where fetch cannot resolve a chrome-extension:// URL; passing a dataType other than text/json/base64.
Related errors
AI-assisted analysis of adam-p/markdown-here@e00d005299 (2026-08-13).
Data as JSON: /api/errors/ab238c7eb451ba24.
Report an issue: GitHub.