adam-p/markdown-here · error · Error

HTTP error status

Error message

HTTP error status: ${response.status}

What it means

getLocalFile(url, dataType, callback) wraps fetch() to read extension-bundled local resources and rejects any non-2xx response by throwing `HTTP error status: <status>` when response.ok is false. The function is documented as expecting local files that 'are not expected to fail'; a non-OK status is treated as an exceptional condition rather than a recoverable return value. Because the throw happens inside the fetch .then chain and getLocalFile does not return the promise, it surfaces downstream as the wrapped rejection in error [3].

Solutions

  1. Verify the url exists at the exact path passed and log chrome.runtime.getURL(url) to confirm the resolved extension URL.
  2. Add the resource to manifest.json web_accessible_resources (and match the right extension/extension_ids) if it is fetched from a web context.
  3. Correct a relative path by passing it through the project's getURL()/chrome.runtime.getURL() helper first.
  4. If the file may legitimately be absent (e.g. the test-file existence check noted in the TODO), refactor to return the promise so the caller can branch on status instead of throwing.

Example fix

// before
getLocalFile('defaults.json', 'json', cb); // 404 → throws HTTP error status: 404

// after — ensure correct extension-relative URL and manifest entry
getLocalFile(chrome.runtime.getURL('defaults.json'), 'json', cb);
// manifest.json:
// "web_accessible_resources": [{ "resources": ["defaults.json"], "matches": ["<all_urls>"] }]
Defensive patterns

Strategy: try-catch

Validate before calling

// Best-effort pre-flight: resolve the extension URL and confirm it is in
// web_accessible_resources before calling getLocalFile.
function resolveLocalUrl(rawUrl) {
  const fullUrl = (typeof chrome !== 'undefined' && chrome.runtime)
    ? chrome.runtime.getURL(rawUrl)
    : rawUrl;
  return fullUrl;
}
// Note: a 200 cannot be fully guaranteed without fetching; pair with try-catch.

Try / catch

// getLocalFile surfaces failures as an unhandled rejection, not via callback,
// so wrap it in a promise you control.
function getLocalFileP(url, dataType) {
  return new Promise((resolve, reject) => {
    getLocalFile(url, dataType, resolve);
    // rejection path: attach a window-level unhandledrejection listener, or
    // refactor getLocalFile to return its promise (preferred).
  });
}
// Preferred: refactor getLocalFile to `return fetch(url).then(...)` and let the
// caller do `.catch(err => { if (/HTTP error status: (\d+)/.test(err.message)) ... })`.

Prevention

When it happens

Trigger: fetch() resolves with a 404/403/500 (etc.) for the given url — most commonly a file path that does not exist, a file not listed in the extension manifest's web_accessible_resources, or a URL resolved against the wrong base. Also a relative url that was not converted with chrome.runtime.getURL before being passed in.

Common situations: Asset was renamed or moved but the caller still requests the old path; new resource added but not declared in manifest.json web_accessible_resources (causing 404/forbidden in extension context); path typos; deploying to a context where chrome.runtime.getURL was not applied so the URL resolves against the document origin instead of the extension.

Related errors


AI-assisted analysis of adam-p/markdown-here@e00d005299 (2026-08-13). Data as JSON: /api/errors/7ba6f5bffa329b9c. Report an issue: GitHub.

Appendix: source

Thrown at src/common/utils.js:301

    return url;
  }

  return chrome.runtime.getURL(url);
}


// Makes an asynchronous XHR request for a local file (basically a thin wrapper).
// `dataType` must be one of 'text', 'json', or 'base64'.
// `callback` will be called with the response value, of a type depending on `dataType`.
// Errors are not expected for local files, and will result in an exception being thrown asynchronously.
// TODO: Return a promise instead of using a callback. This will allow returning an error
// properly, and then this can be used in options.js when checking for the existence of
// the test file.
function getLocalFile(url, dataType, callback) {
  fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(`HTTP error status: ${response.status}`);
      }

      switch (dataType) {
        case 'text':
          return response.text();
        case 'json':
          return response.json();
        case 'base64':
          return response.blob();
        default:
          throw new Error(`Unknown dataType: ${dataType}`);
      }
    })
    .then(data => {
      switch (dataType) {
        case 'text':
        case 'json':
          callback(data);

View on GitHub (pinned to e00d005299)