# How the MAX_VECTOR_PMTILES_ZOOM Constant Stays Synchronized with the WASM Binary in GeoLibre

> Discover how GeoLibre ensures MAX_VECTOR_PMTILES_ZOOM stays in sync with its WASM binary. A runtime test validates the limit, preventing version mismatches and ensuring seamless operation.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: internals
- Published: 2026-08-05

---

**GeoLibre enforces synchronization between the TypeScript constant and the internal WebAssembly binary limit through a runtime unit test that validates the ceiling value and immediately detects any version mismatch.**

The **MAX_VECTOR_PMTILES_ZOOM** constant in GeoLibre defines the maximum zoom level allowed when generating vector PMTiles archives. Because the underlying WASM tool contains a hard-coded internal limit that is not exported programmatically, the repository relies on a specific validation strategy to ensure the TypeScript constant always matches the binary’s behavior.

## Where MAX_VECTOR_PMTILES_ZOOM is Defined

The constant is declared in **[`packages/processing/src/wasm-convert.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/wasm-convert.ts)** and exported for consumer use:

```typescript
export const MAX_VECTOR_PMTILES_ZOOM = 18;

```

This value represents the highest zoom level that can be passed to the `vector_to_pmtiles` WebAssembly tool. The constant is used throughout the processing pipeline to validate inputs before they reach the WASM boundary, preventing unnecessary computation on requests that the binary would reject.

## The Internal WASM Limitation

The `vector_to_pmtiles` tool compiled to WebAssembly contains an internal hard-coded ceiling. When invoked with a `--max_zoom` argument exceeding this limit, the binary aborts with a validation error:

```

validation error: max_zoom must be <= 18

```

Because the WASM binary does not expose this limit through an exported function or metadata property, the TypeScript codebase cannot query the value dynamically at runtime. This architectural constraint necessitates a manual synchronization strategy backed by automated testing.

## Runtime Validation Through Testing

Synchronization is enforced in **[`tests/wasm-convert.test.ts`](https://github.com/opengeos/GeoLibre/blob/main/tests/wasm-convert.test.ts)** through a unit test that treats the WASM binary’s error message as the source of truth. The test verifies that the constant matches the actual behavior of the current binary version.

### How the Test Validates the Ceiling

The test suite calls `tileVectorToPmtiles` twice: once at the documented limit and once beyond it. According to the source code, the implementation looks like this:

```typescript
it("accepts the documented maximum zoom and rejects one deeper", async () => {
  // succeeds at the cap
  const atCap = await tileVectorToPmtiles(
    { name: "points.geojson", data: pointsGeoJson },
    "cap.pmtiles",
    { minZoom: MAX_VECTOR_PMTILES_ZOOM, maxZoom: MAX_VECTOR_PMTILES_ZOOM },
  );
  assert.ok(hasMagic(atCap.data, PMTILES_MAGIC));

  // fails one level beyond the cap
  await assert.rejects(
    tileVectorToPmtiles(
      { name: "points.geojson", data: pointsGeoJson },
      "over.pmtiles",
      { maxZoom: MAX_VECTOR_PMTILES_ZOOM + 1 },
    ),
    /max_zoom must be <= 18/i,
  );
});

```

This test guarantees two critical behaviors:
- The tool succeeds when `maxZoom` equals **MAX_VECTOR_PMTILES_ZOOM**, confirming the constant represents a valid ceiling.
- The tool throws the expected error when the zoom exceeds the constant, confirming the constant has not fallen behind a raised WASM limit.

### The Error Message Contract

The regular expression `/max_zoom must be <= 18/i` creates a strict contract between the TypeScript code and the WASM binary. If the binary’s internal limit changes (for example, to support zoom level 20), this test will fail because:
1. The first assertion will fail if the new limit is lower than 18.
2. The rejection assertion will fail if the new limit is higher than 18 and the error message changes.

## Synchronization Workflow When Updating Dependencies

When the `geolibre-wasm` dependency is updated—typically via a Dependabot pull request—developers must verify whether the internal zoom ceiling has changed. The documented workflow involves:

1. **Binary Update**: A new version of the WASM binary is pulled into the repository.
2. **Manual Verification**: Developers inspect the WASM source or run the binary to identify the new hard-coded limit.
3. **Constant Update**: They modify `MAX_VECTOR_PMTILES_ZOOM` in [`packages/processing/src/wasm-convert.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/wasm-convert.ts) to reflect the new value.
4. **Automated Guard**: The unit test in [`tests/wasm-convert.test.ts`](https://github.com/opengeos/GeoLibre/blob/main/tests/wasm-convert.test.ts) runs in CI and will fail if the constant does not match the binary’s actual behavior, preventing a merge of an out-of-sync configuration.

This process is documented in **[`CLAUDE.md`](https://github.com/opengeos/GeoLibre/blob/main/CLAUDE.md)** under the "MAX_VECTOR_PMTILES_ZOOM" section, which serves as a reminder to re-check the constant after any `geolibre-wasm` bump.

## Practical Usage Examples

When building PMTiles archives, import the constant from `@geolibre/processing` to ensure your application respects the current binary limits:

```typescript
import { tileVectorToPmtiles, MAX_VECTOR_PMTILES_ZOOM } from "@geolibre/processing";

// Create a PMTiles archive at the maximum supported zoom level
await tileVectorToPmtiles(
  { name: "roads.geojson", data: geojsonBytes },
  "roads.pmtiles",
  { minZoom: 0, maxZoom: MAX_VECTOR_PMTILES_ZOOM },
);

```

Attempting to process tiles beyond the limit will throw the same validation error emitted by the WASM binary:

```typescript
// This call will reject with "max_zoom must be <= 18"
await tileVectorToPmtiles(
  { name: "roads.geojson", data: geojsonBytes },
  "roads.pmtiles",
  { maxZoom: MAX_VECTOR_PMTILES_ZOOM + 1 },
);

```

## Summary

- **MAX_VECTOR_PMTILES_ZOOM** is defined in [`packages/processing/src/wasm-convert.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/wasm-convert.ts) with a value of `18`.
- The WASM binary contains a matching hard-coded limit that triggers a validation error when exceeded.
- Because the binary does not export this limit, synchronization relies on a runtime unit test in [`tests/wasm-convert.test.ts`](https://github.com/opengeos/GeoLibre/blob/main/tests/wasm-convert.test.ts) that validates the constant against the binary’s actual error behavior.
- When the WASM binary updates, developers must manually update the constant; the test suite acts as an automated gate to catch any oversight.

## Frequently Asked Questions

### Why doesn't the WASM binary export its maximum zoom limit directly?

The `vector_to_pmtiles` tool was designed with a hard-coded validation check rather than a configurable or queryable parameter. The WebAssembly interface does not expose metadata about these internal limits, requiring the TypeScript wrapper to maintain a parallel constant that mirrors the binary’s compiled-in constraints.

### What error message appears when exceeding the maximum zoom?

When you provide a `maxZoom` value greater than **MAX_VECTOR_PMTILES_ZOOM**, the WASM binary aborts with the error: `validation error: max_zoom must be <= 18`. This message is case-insensitive and is used by the test suite to verify synchronization between the constant and the binary.

### How do I update the zoom limit when the WASM binary changes?

First, determine the new internal limit by inspecting the updated WASM source or running the binary manually. Then update the `MAX_VECTOR_PMTILES_ZOOM` constant in [`packages/processing/src/wasm-convert.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/wasm-convert.ts) and adjust the expected error message in [`tests/wasm-convert.test.ts`](https://github.com/opengeos/GeoLibre/blob/main/tests/wasm-convert.test.ts) if necessary. The CI pipeline will confirm your update is correct when the unit tests pass.

### Where is this synchronization behavior documented?

The synchronization workflow and the rationale behind the **MAX_VECTOR_PMTILES_ZOOM** constant are documented in **[`CLAUDE.md`](https://github.com/opengeos/GeoLibre/blob/main/CLAUDE.md)** within the repository root. This file contains specific reminders to verify the constant whenever the `geolibre-wasm` dependency is updated via automated pull requests.