perspective-dev/perspective · error · TypeError
TileSourceSpec.template must contain
Error message
TileSourceSpec.template must contain "${placeholder}" What it means
After validating the template string, parseTileSourceSpec requires the {z}, {x}, {y} placeholders so the tile URL can be filled with zoom/x/y coordinates per tile request. A template missing any of these (e.g. a plain WMS URL or a typo like {Z}) cannot be used by the tile layer.
Solutions
- Include all three placeholders, e.g. https://tile.example.com/{z}/{x}/{y}.png
- Fix casing/typos in placeholders ({Z}/{X}/{Y} are not matched)
- Use a template from a standard raster XYZ tile provider as reference
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/viewer-charts/src/ts/map/tile-source.ts:152 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of perspective-dev/perspective@11c8238c0c (2026-09-09).
Data as JSON: /api/errors/75ad0d298b24e91c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/viewer-charts/src/ts/map/tile-source.ts:152
const raw = input as Record<string, unknown>;
const str = (key: string): string => {
const v = raw[key];
if (typeof v !== "string" || v.length === 0) {
throw new TypeError(
`TileSourceSpec.${key} must be a non-empty string`,
);
}
return v;
};
const id = str("id");
const label = str("label");
const template = str("template");
const attribution = str("attribution");
for (const placeholder of ["{z}", "{x}", "{y}"]) {
if (!template.includes(placeholder)) {
throw new TypeError(
`TileSourceSpec.template must contain "${placeholder}"`,
);
}
}
const rawSubdomains = raw["subdomains"] ?? [];
if (
!Array.isArray(rawSubdomains) ||
rawSubdomains.some((s) => typeof s !== "string" || s.length === 0)
) {
throw new TypeError(
"TileSourceSpec.subdomains must be an array of non-empty strings",
);
}
const subdomains = Object.freeze([...rawSubdomains] as string[]);
if (template.includes("{s}") && subdomains.length === 0) {
throw new TypeError(View on GitHub (pinned to 11c8238c0c)