Skip to content

Troubleshooting

Start with what the map itself says: in most cases it names the problem and the fix. Then find your symptom in the tables below; each row links to the page that explains it.

<ml-map> and <ml-scrollytelling> (and the Astro components, which render them) report problems on the page, not only in the browser console:

  • Error card (replaces the map). The document can’t render at all: a YAML syntax error, a validation error (with its line number and, for a typo, a “did you mean”), a src file that isn’t found (with the full address the browser requested; a wrong path that returns a web page is recognised as one), a page opened from a file (file://, which browsers block; the card says to start a local server), or a basemap style that won’t load. Fix what the card names and reload. For page scripts, mapReady() rejects.
  • Notice (over the map, dismissible). The map works but part of the document didn’t load: a layer MapLibre rejected (for example a bad colour inside an expression), a layer whose source: names a source that doesn’t exist, a data file that didn’t load, or an images: entry or marker icon that failed. Each line names the layer or file. The notice is written for two readers: it leads with “Part of this map couldn’t load” for anyone visiting the site, and keeps the fix in a “Details for the site’s author” section below it, open while you develop and closed on a published site, where a click opens it. The map still fires ml-map:load.
  • Author hints (in the same notice). The map works, but the document probably doesn’t say what you meant: a “did you mean” for a near-miss name, a key nested under config: that belongs at the top level, a fitTo typo, a center or bounds that looks written [latitude, longitude], a before: naming a layer the map doesn’t have, a chapter naming a missing layer, a value starting with the reserved =. These are for you, not your visitors, so they show only while you develop (below). A notice holding only hints leads with “Notes for this map’s author”.
  • Height hint. A map with no height is invisible, so the element shows a short note saying to give it one, and removes it once the map has a height (The map has no height).
  • “Loading map…” in the middle of the map. Not a problem report: while the map starts, the element carries aria-busy="true", and if it hasn’t drawn after about a second (usually a slow basemap, or a fitTo data file still arriving) a small, muted “Loading map…” appears (role="status"). Both go away when the basemap draws or an error card replaces the map, so a fast map never shows it. quiet doesn’t hide it; a page with its own loading indicator hides it with ml-map .ml-map-loading { display: none; }. The text is translatable as maplibre-yaml.Loading in locale: (Accessibility & languages).

Everything is also written to the browser console, so open the developer tools (F12, or Ctrl+Shift+I; ⌥+⌘+I on a Mac) when the page says nothing. To catch mistakes before you load the page, run npx maplibre-yaml validate map.yaml (The CLI) or set up your editor to check the YAML as you type. Page scripts can listen for the same problems as events (ml-map:error and the others).

Failures always show. Author hints show when any of these is true, and stay off the page otherwise:

SituationAuthor hints
The page is served from your computer: localhost, 127.0.0.1, [::1], 0.0.0.0 or [::] (a dev server started with --host), or opened as a file:// pageshown
A bundler development build: astro dev, vite (their import.meta.env.DEV), on any address, a Codespaces URL includedshown
The element has the debug attribute (or its <ml-scrollytelling> does; in Astro, the debug prop)shown, wherever the page is served
A published site (GitHub Pages, Netlify, your own domain), including the plain CDN script, which can’t know how it was builthidden
The element has quiethidden, and so are failures

Every hint is still written to the browser console, wherever the page runs.

To check a deployed site, add debug to see the author hints there:

<ml-map src="/maps/city.yaml" debug></ml-map>

Add quiet to keep the notice (failures and hints) and the height hint off the page, for a production site that would rather fail quietly. The problems are still logged to the console and dispatched as events. quiet wins over debug. The error card is always shown.

<ml-map src="/maps/city.yaml" quiet></ml-map>

The Astro Map, FullPageMap and Scrollytelling components take the same two as props: <Map src="…" debug />.

SymptomWhere to look
Nothing at all where the map should be, no errorThe element has no height: The map has no height
A blank page, and Failed to resolve module specifier “maplibre-gl” in the consoleThe import map is missing: Browser usage (CDN)
The page was opened by double-clicking the HTML file (a file:// address)Serve the folder instead: Run a local server
A blank map and Worker failed to loadmaplibre-gl 6 inside a bundler needs its worker set: Worker failed to load
The element stays empty and customElements.get("ml-map") is undefined<ml-map> isn’t defined
An error card (“Configuration Error”)An error card instead of the map
YAML syntax error … <!doctype html> after npm run buildThe YAML is next to index.html instead of in public/: YAML next to index.html
The map refuses to load and says it has no basemapAdd mapStyle: under config:: Map styles
The map is in the ocean, or far from your dataCoordinates are [longitude, latitude]: Coordinates
SymptomWhere to look
The basemap draws, your layer doesn’tThe basemap draws but your layer doesn’t
A data file on another site doesn’t load (a CORS error in the console)CORS considerations
”CSV files aren’t supported”Convert the table to GeoJSON: CSV and spreadsheets
A colour is ignored, or the layer fails validationPut colours in quotes: in YAML # starts a comment (Adding a simple layer)
A warning about a value starting with =Strings starting with = are reserved
A local data file isn’t foundPaths are relative to the page, not the YAML: Using your own data file
Your page’s JavaScript never sees the map’s eventsEvents not firing

Works on your computer, not once published

Section titled “Works on your computer, not once published”
SymptomWhere to look
A 404 for the YAML or the data on GitHub Pages (or any site under a subpath)Set the base: Publishing & subpaths (HTML pages, Astro)
Every file 404s on your computer after adding basePreviewing a subpath
Author hints you saw while developing are goneExpected: they show only while you develop; add debug to see them (above)
Something changed after upgradingUpgrading to 0.9

What you see: nothing where the map should be, no error, or a map a few pixels tall. Unless it has quiet, the element shows a short note asking for a height.

<ml-map> has no size of its own, and neither does a <div> you hand to the JavaScript API. Give it a height and display: block:

ml-map {
display: block; /* required: a custom element is inline by default */
width: 100%;
height: 400px; /* or 100vh to fill the window */
}

The Astro Map component sets a height for you (400px by default, the height prop changes it), and FullPageMap fills the window. A component of your own around <ml-map> needs both properties: <ml-map src="/configs/map.yaml" style="height: 400px; display: block;" />.

What you see: the element is on the page but stays empty, and customElements.get("ml-map") in the console returns undefined.

The script that registers the element didn’t run:

  • From a CDN: the page needs both the import map for maplibre-gl and the register.js script, as in Browser usage (CDN). A Failed to resolve module specifier “maplibre-gl” error in the console means the import map is missing or comes after the script.
  • With a bundler: import @maplibre-yaml/core/register in code that runs in the browser (Using a bundler).
  • In Astro: import it in a <script> tag, never in the frontmatter (HTMLElement is not defined), or use the package’s <Map> component, which does it for you.

What you see: the map area stays empty, or shows a Map Error card saying Worker failed to load; the console names maplibre-gl-worker.mjs.

maplibre-gl 6 draws in a background worker loaded from a separate file, and inside a bundle (Vite, Astro, webpack) it can’t find that file unless it is told where it is. Add the worker lines next to the register import:

import { setWorkerUrl } from "maplibre-gl";
import workerUrl from "maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url";
import "@maplibre-yaml/core/register";
setWorkerUrl(workerUrl);

The CDN page needs nothing (the worker loads from the CDN), and on maplibre-gl 4 or 5 leave these lines out. The @maplibre-yaml/astro components set the worker for you; a component of your own around <ml-map> does it in its <script> (Using <ml-map> directly). Details: Using a bundler (Vite).

What you see: a card in place of the map (for example “Configuration Error”) listing the problem with its line, such as id: The document is missing id: — add id: a-short-name.

The document failed to load, parse or validate. The card names the field; the common causes:

  • Indentation. YAML nests by indentation: use spaces (two per level), never tabs, and keep sibling keys at the same depth.

    # Wrong: zoom is indented differently from center
    config:
    center: [-74, 40]
    zoom: 10
  • A missing required key. A map needs type: map, an id, and a config: with center and zoom; without mapStyle (the basemap) it warns in validation and the page shows an error card.

    type: map
    id: my-map
    config:
    center: [-74.006, 40.7128]
    zoom: 10
    mapStyle: "https://tiles.openfreemap.org/styles/liberty"
    layers: []
  • A wrong value. center is [longitude, latitude] (two numbers), not a place name; colours go in quotes, because in YAML # starts a comment.

  • A file that isn’t found. The card shows the address the browser asked for. Paths are relative to the page, or under public/ with a bundler or Astro; on a site under a subpath, see Publishing & subpaths.

YAML inside a JavaScript template literal or a <script type="text/yaml"> tag has its own indentation pitfall: Template literal YAML issues.

The basemap draws but your layer doesn’t

Section titled “The basemap draws but your layer doesn’t”

First read the notice at the top of the map, if there is one: it names each layer that didn’t draw and each data file that didn’t load, with the address the browser tried. Then check:

  1. The path. Relative data paths resolve against the page, not the YAML file (Using your own data file). On a site under a subpath, set base (Publishing & subpaths).

  2. The file. Open its URL in the browser: it should be GeoJSON, not a web page or a 404. In the developer tools’ Network tab, find the request.

  3. CORS. A file on another site must allow your page to read it; the console shows a CORS error if not (CORS considerations).

  4. The features. A file with no features, or features without geometry, loads but draws nothing. Page scripts can log what loaded:

    const mapEl = document.querySelector("ml-map");
    mapEl.addEventListener("ml-map:layer-data-loaded", (e) =>
    console.log("Loaded:", e.detail.layerId, e.detail.featureCount)
    );
    mapEl.addEventListener("ml-map:layer-data-error", (e) =>
    console.error("Error:", e.detail.layerId, e.detail.error)
    );
  5. The style. A colour without quotes, a filter: that matches nothing, or a minzoom above the current zoom hide a layer that did load.

Large data: PMTiles, FlatGeobuf, GeoParquet and COG

Section titled “Large data: PMTiles, FlatGeobuf, GeoParquet and COG”

When one of these files fails, the rest of the map still draws and the notice says why. The common messages, with the fix for each, are in When something goes wrong.

SymptomWhere to look
”served without range-request support”, often with python -m http.serverUse a server with range requests (npx serve, GitHub Pages, Netlify, S3): Range requests and CORS
A 416 status (Range Not Satisfiable)The file was found, but the server refused the part asked for: the upload may be incomplete, or the server doesn’t serve parts of files correctly. Upload the file again, or try another host (Range requests and CORS)
A file on another site is blocked (CORS)The other server must allow your site and the Range header: CORS rule
”is in EPSG:…” (the wrong projection)FlatGeobuf needs longitude/latitude (EPSG:4326), a COG Web Mercator (EPSG:3857); the notice gives the command that converts it (details)
“The … reader (…/chunks/….js) couldn’t be downloaded”, on a site hosting maplibre-yaml’s files itselfCopy the whole dist/ folder, not only register.js: Hosting the files yourself
A Protomaps basemap draws without labels or icons, or the notice names the fonts or iconsLabels come from Protomaps’ font host unless you copy them: Host your own basemap
”too large to load whole in a browser”Add load: viewport or convert the file: When something goes wrong
SymptomWhere to look
ReferenceError: HTMLElement is not definedHTMLElement is not defined
A saved YAML change doesn’t appear in astro devEditing in astro dev
<Map src> gives a 404src is the address on the site, without public/: Incorrect src path
A page using loadMapConfig fails with ENOENT on a serverServer output (SSR)
More Astro problemsAstro troubleshooting
SymptomWhere to look
mlym: command not found, or npx mlym fails with a 404Use npx maplibre-yaml, or install the CLI: Short alias, Command not found
No autocomplete or checking in your editorEditor setup
mlym validate errors don’t show in VS Code’s Problems panelValidate on save (VS Code task)