All Posts

Debugging 101 with Stamen Carto Tools (and other tools we like)

In vector cartography, the map is only as good as the data that powers it. If we don’t understand what’s going on in the underlying data, we’re pretty limited in our cartographic approach. A major part of this work involves parsing vector tile data, determining how one dataset compares to another, and diagnosing bugs encountered during the design process. 

As part of our cartography work at Stamen, we’ve developed several tools to help make map design projects of any size faster, easier, and more collaborative. In this blog post we’ll outline some ways that we debug using our open source tools, complemented by some non-Stamen tools we like as well. A few of these tools were recently highlighted in Awesome Maplibre: A collection of awesome things that use or support MapLibre! – we’re glad others find them useful, too!

When putting ideas for this post together, the team found that there are many different types of debugging that we routinely encounter on cartography projects, each requiring slightly different solutions. These roughly fall into a few buckets: understanding data, finding issues with stylesheets, and optimizing how tiles and styles work together.

Understanding data

Often, clients will have a general idea of the primary use case for their cartography project when they first come to us. Usually (but not always!), they bring data with them from one of a handful of data providers and formats we are familiar with (i.e. OSM, HERE, Tilezen, Mapbox, OpenMapTiles, etc.) that meshes well with the type of map we are creating. This is ideal for us, as we have worked with all of these sources many times before and are well aware of what features and attributes they have available.

The same area with Mapbox’s Dark style (featuring their data) on the left and Stamen’s Toner style (which is powered by Stadia tiles), as seen in Maperture.

Sometimes, a client will have their own version of an existing dataset with modifications for their use case, such as a cut of OSM tiles with additional data added or unneeded data removed. One of our core tools, Maperture, allows us to easily investigate what the tiles contain if we have a style to start from. You can select any feature and see a pop-up with its attributes clearly listed:

The same area with Mapbox’s Light style (featuring their data) on the left and the Monochrome Light style we designed for AWS (which is powered by HERE tiles). The same road is selected for both, with its attributes visible in the window pop-up.

Another tool we love for this use case is Vector Inspector, created by friend of Stamen Steve Bennett, which renders all features from an endpoint as separate layers on a simple basemap. This can be incredibly helpful, as it shows you everything available in the tiles:

We can see all features in this area from a single tile source via Vector Inspector.

Vector Inspector has the added benefit of letting you see all possible values within a given view, where you can select and highlight a specific value you may be looking for:

We can easily highlight a specific type of feature (here, neighborhood boundaries).

Between these two, Maperture is best for comparing sources to one another in a single pane, assuming you have styles that use them already (for example, comparing how an area looks with pure OSM data vs. with Mapbox data). 

The same area with the AWS Standard Light style featuring HERE data on the left and the same style with Grab data on the right. Grab specializes in high resolution data in southeast Asia.

You can also interrogate multiple tile sources at once in Maperture, whereas Vector Inspector is limited to one endpoint at a time. This is useful for many of our clients, who often have a core set of tiles powering their basemap with an additional source like traffic or custom points of interest as well.

The two panes with the same map (Stamen Terrain, powered by Stadia tiles). Details about the global landcover source are visible on the left, with the core Stadia OpenMapTiles visible on the right.

We love the concept of an “x-ray mode”, where you can see all the data in your tiles, lightly styled, with some indication of what is currently rendered by your styles. Mapbox’s version of this is great, but we don’t often work in Mapbox Studio given it requires sources hosted by Mapbox. Maputnik has a version of this too called “inspect view“, but it requires a TileJSON in order to see all the data, which our clients often don’t have. X-ray mode is an area where we’re thinking about how to improve our open source tooling to solve some of these problems.

We often develop using MapLibre, as many of our clients have moved towards using open source software where possible. Maperture allows you to compare differences in rendering between MapLibre GL, Mapbox GL, Leaflet, and so on. The more developed MapLibre GL becomes, the more we will start to see noticeable differences between MapLibre GL and Mapbox GL.

The two panes with the same map (Stamen Toner, powered by Stadia tiles). The left is rendered with Mapbox GL JS, while the right uses MapLibre GL JS. You can see a slight difference in how the road label for Southern Embarcadero Fwy renders (it’s smoother in MapLibre).

Both Maperture and Vector Inspector make it easy to interrogate our tiles and understand where data is or isn’t, where it first appears as we zoom in, and where attributes might not be what we expect. Maperture is at the core of our development environment as we work on vector cartography at scale.

Finding issues with stylesheets

One of our top debugging use cases is figuring out why stylesheet properties aren’t having the intended effect on our tiles. When used in concert with our Map GL Style Build tooling, we can easily iterate on stylesheet development and see how the output differs from our production style:

Not a bug per se, but we can quickly try other colors via Map GL Style Build and a local instance of Maperture as we iterate on design.

These tend to be either data issues (known or unknown) or bugs in how the stylesheet is written. Stylesheet authoring is an art, not a science – there are often a few ways to tackle a specific problem and pros and cons for each approach.

Maperture has great renderer error messages if you open the console, which helps tremendously when figuring out why something is not working. 

I purposefully entered the wrong formatting for the color value we want to use and the console points me to the right place to fix it.

You can also check for regressions or unintended changes with our highlight differences mode, which will scan the old and new versions of your style and call out any changes. It can find even the tiniest change, which can be very helpful when iterating on complicated styling.

Confession: highlight differences mode is how I found the rendering difference between Mapbox GL JS and MapLibre GL JS seen earlier

Sometimes, there’s an issue in how we’ve written a filter in the stylesheet – perhaps an expression is formatted incorrectly or we’re using the wrong expression type for a given attribute. In other cases, everything may be written with proper syntax, but the values we are searching for in the tiles don’t match exactly (ex. we are looking for class == primary but it should actually be kind == primary). 

Most often, bugs involve combinations of feature attributes that aren’t written properly. We don’t have great tooling for finding these combinations (ex. we need both class == primary and link == true to select and style ramps for primary roads), but this is another issue we would really like to solve.

We have an interactive legend tool called Chartographer that is immensely helpful in calling out stylesheet inconsistencies. Perhaps both major and minor city labels look fine on their own, but something about how they work together on the map is off. With Chartographer, you can easily see how colors, line widths, and symbol layers render at each zoom level. 

A cross-section of Toner’s symbol layers via Chartographer

It can be much easier to pinpoint the cause of an issue (ex. maybe one layer appears too late or changes styling at a different zoom level than intended) when you have a nice cross-section of your style.

Looks like something in our style is changing these colors dramatically but still including some overlap between road-street and road-street-low…this would be a good place to investigate a potential bug.

Chartographer is purely style-based, though, so don’t expect any insight into how styling and data interact with one another.

When we find inconsistencies in styles, we use Map GL Style Build to address them and, often, prevent them from regressing or happening again elsewhere down the line. Map GL Style Build allows for as much variablization as you want in whatever format works best for your setup.

For example, if we want all of our 70+ road layers to start with one set of colors and transition to a different set as you zoom in, we can set this up to happen the same way across them all with variables. You can variablize entire expressions, which really helps reduce the amount of human error working on multiple styles can introduce.

Here, we variablized entire expressions so all road layers that were classified as links would scale at the same rate without us needing to write this expression several times.

Map GL Style Build is great for quick iteration when you have multiple stylesheets and provides helpful error messaging when something isn’t set up or written properly. To really up your debugging game, Map GL Style Build is flexible enough to allow for a debugging style setup if the other tooling we’ve talked about isn’t providing the type of insight you need. Setting up a new style takes a bit of effort with Map GL Style Build, but it makes the process so much smoother later that we find it to be more than worth the time upfront.

A custom debug style we created for a client project, which renders all data in the tiles. This version assumes styling in our production stylesheet (ex. line widths) to help parse what we already have vs. what else is available in the tiles.

A custom debug style doesn’t have to be as elaborate as creating your own complete x-ray style; you can also easily make a duplicate of your current style and just add a simple additional debug layer to it. This can be especially useful if you only need to debug a specific aspect of your style, or to hunt down uncommon features in the data to make sure you’re styling them correctly. 

A debug layer enabled on top of our current style, highlighting any roads with more than 7 lanes. A quick one-off debug overlay like this can save a lot of time that would otherwise be wasted hunting around on the map looking for uncommon tags or other data edge cases.

Optimizing how tiles and styles work together

Another major area we focus on when debugging is performance optimization. With vector cartography, the source of performance issues is most often the tiles themselves rather than the stylesheet. Vector Inspector makes it very easy to see all the attributes available in tiles, especially those your stylesheets aren’t using. Assuming your tiles aren’t supporting other styles or uses for your product, unused attributes are a simple way to improve tile size and, ultimately, stylesheet performance.

Here, we can see the attribute selected (“indoor”) has no features in this area. Once we confirm we aren’t using it in our style elsewhere, we can safely remove these from the tiles.

On the stylesheet side, we have a sense of how performant a map is based on its number of layers, expression complexity, and additional assets required, like fontstacks and spritesheets. We will frequently go through styles in Map GL Style Build and purge anything not used in stylesheets. We use linters internally to optimize less performant expressions or simplify expressions where possible without compromising the map’s look.

Example of an expression that our linter would optimize when styles build from templates in Map GL Style Build. This would be rewritten to replace the match statements with == expressions, which are more performant.

Diagnosing major performance issues, like stylesheet authorship, is by no means an exact science. So many factors come into play when loading a map on a device (such as device type, network connection, caching, etc.) that it can be hard to tell what might be causing major issues. Having more helpful tooling that can make it easier to debug the entire stack would be another great area for us to explore in the future.

How do you debug?

We hope this was an interesting peek behind the curtain at how Stamen works quickly and efficiently on vector cartography projects. Stamen uses all of these tools together and they are part of our special sauce – let us know if we can help improve your mapping workflows or jumpstart a cartography project you’ve been thinking about.

If you’d like to learn more about our tooling, we’ll be talking about some of these workflows at the upcoming State of the Map US 2025 in Boston, MA. Hope to see you there!

Are there any handy tools we’ve missed? What map style debugging pain points do you wish these tools could solve? Building and maintaining these tools is important to us and there is always room for improvement! Drop us a line with any thoughts or questions.

Published: 04.30.25
Updated: 05.01.25

About Stamen

Stamen is a globally recognized strategic design partner and one of the most established cartography and data visualization studios in the industry. For over two decades, Stamen has been helping industry giants, universities, and civic-minded organizations alike bring their ideas to life through designing and storytelling with data. We specialize in translating raw data into interactive visuals that inform, inspire and incite action. At the heart of this is our commitment to research and ensuring we understand the challenges we face. We embrace ambiguity, we thrive in data, and we exist to build tools that educate and inspire our audiences to act.