Skip to content

Report set_style and set_filter changes that never reach the map (#409) - #429

Merged
cboettig merged 2 commits into
mainfrom
fix/409-set-style-validation
Nov 4, 2026
Merged

cboettig merged 2 commits into
mainfrom
fix/409-set-style-validation

Conversation

@cboettig

@cboettig cboettig commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Closes #409.

Some models send set_style a style of "" or a whitespace string. setStyle reported success with no updates for an empty string, and for any other string it iterated the characters as property names. Separately, MapLibre reports an invalid paint value or filter through the map's error event rather than by throwing, so set_style and set_filter reported success for changes that never reached the map.

  • setStyle parses a JSON-string style and rejects an empty string, an empty object or an array with an error that shows the expected shape.
  • setStyle and setFilter listen for error events during the MapLibre call. A rejected value is reported with MapLibre's message (for example filter[2]: Expected number but found string instead). A rejected filter is not recorded as the layer's filter.
  • The set_style schema lists the common paint properties, with additionalProperties: true, so constrained decoders have something to generate.

The schema properties have no type, because a paint value may be a string, a number or an expression. That is valid JSON Schema, but it's worth one run on a downstream app with DeepSeek V4 Flash, the model that hit this, before release.

Tests: test/map-manager.map-errors.test.js.

setStyle now parses a JSON-string style and rejects an empty string,
an empty object or an array instead of returning success with no
updates or iterating a string's characters. Paint values and filters
that MapLibre rejects through its error event, rather than by
throwing, are now reported as failures with MapLibre's message, and a
rejected filter is not recorded as the layer's filter. The set_style
schema lists the common paint properties, so constrained decoders have
something to generate.
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 73.93% 10781 / 14582
🔵 Statements 73.9% 10783 / 14590
🔵 Functions 78.82% 428 / 543
🔵 Branches 85.35% 2693 / 3155
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
app/map-manager.js 81.65% 83.98% 79.79% 81.77% 72-166, 203-207, 217-219, 242-244, 246-248, 250-252, 262-272, 276-282, 288-289, 357-359, 361-363, 394-400, 436, 438-439, 458-503, 517-539, 581-582, 666-667, 752-753, 803-839, 854-856, 883-885, 1004-1006, 1084-1085, 1111-1112, 1274-1283, 1320-1321, 1327-1330, 1339-1349, 1355-1362, 1415-1416, 1577-1578, 1635-1639, 1653-1656, 1701-1702, 1708-1711, 1782-1783, 1803-1805, 1827-1832, 1838-1841, 1851-1874, 1881-1888, 1896-1985, 1993-1994, 2125-2126, 2272-2274, 2286-2300, 2362-2364, 2381-2382, 2394-2400, 2645-2646, 2744-2763, 2766-2781, 2892-2898, 2972-2974, 3097-3098, 3131-3135, 486-520
app/map-tools.js 98.83% 87.71% 68.75% 98.83% 160-162, 177-179, 826-827, 834-835
Generated in workflow #339 for commit 64c21aa by the Vitest Coverage Report Action

Tested on ca-30x30 with DeepSeek V4 Flash, which sent "fill-opacity": "1"
as a string when the set_style properties were untyped. Opacity, width and
radius are now typed number or expression, and the same prompt sends 1.

MapLibre 5.22 throws on a filter whose types don't check, such as a match
returning "true"/"false", instead of firing its error event, so the
agent got a generic tool error. That throw is now reported the same way:
the filter is rejected and the layer is unchanged.
@cboettig
cboettig merged commit ebf69fc into main Nov 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

set_style accepts an empty-string style, reports success, and leaves the map unchanged

1 participant