adam-p/markdown-here · error · Error

HTTP error status: ${response.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].

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)

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.