A query almost never fails loudly. It shows a map with one layer missing, or a panel with no widget, or a legend that never appears — and the cause is usually one of the items below. The list is short because it is the result of reading the whole body of queries running in production: these are the things that actually go wrong.

1. The query produced nothing

SymptomCauseFix
Only the default background is shownThe query text is not a single expression (a top-level var, a statement, a stray semicolon), so it threw before producing a valueSee the query language §1
Same, with no error in the consoleThe expression evaluated, but its value was not an array of layer definitionsEnd the expression with the array
One layer missing, others fineIts name is not in the catalogue, or its server was registered after the array that uses itCheck the name; put addRemoteWMSServer before the array
A calculated layer stays emptyA map in name is not published with the operation the query asks for; the console says Operation X is not defined for layer YUse a decoding the map offers
this.something is not a functionAn arrow function where the platform binds this to the layerRegular function for beforeCalc, handler, functions.*, the vector callbacks
A value is undefined only inside expressionIt came from a closure, a global or the DOM, none of which exist in the calculation workerCompute it in beforeCalc, pass it as an input
Cannot read properties of undefined (reading '<id>') from expressioninputs.id[ID] used inside expression: the inputs reach the worker as JSON, which keeps only the array’s elements, so the id map is goneRead by position: inputs[0] is the first input widget in descriptionHtml. inputs.id[ID] works only on the page (beforeCalc, functions, …)
filterLegends[...].color.join is not a functionsetCalculateLegend given a CSS colour ("#c0392b"): the legend entries take [R, G, B]{ color: [192, 57, 43], value: 1, title: "Above 800 m" }. Layer and group color properties do take CSS colours
An input changes, the countdown runs out, the map stays the samebeforeCalc called setCalculateLegend with the same legend as before: an unchanged legend skips the redraw, so the new inputs never reach the tilesMake the legend follow the inputs - list only the classes shown, or put the value in a title ("Above " + value + " m"), as the documentation examples do
Works once, then breaks on re-applyState kept outside the query’s globalssetQueryGlobalProperties
“Global variable can’t be redefined”A global name collides with one the page already hadRename it
A widget’s tag renders as nothingUnknown tag name; the console shows {{MARKUP}} INVALID OBJECT NAMEUse the exact tag from the widget markup language

2. Keys that are silently ignored

These appear in real queries — some in dozens of them — and have no reader in the platform. Nothing warns about them, which is exactly why they spread by copy-paste. Remove them; they document an intent the map never had.

KeyWhere it is writtenWhat people expectWhat happens
closedGroupOn a groupStart the group collapsedNothing. Groups start collapsed by default; use openGroup: true to start one expanded
disableDownloadOn a layerHide that layer’s download buttonNothing. It only exists as a page option (options=disabledownload in the URL), which applies to the whole page
hideBottomButtonOn a layerHide the query button under the layer rowNothing at layer level. It works only inside a paramsButtonConfig entry of type query
legendIdOn a layerPoint the layer at a legendNothing. It is a parameter of the legendhtml widget
maxZoomRealOn a layerA second maximum zoomNothing. maxZoom is the one that is read
showTimelineButton, timelineConfigOn a layerConfigure a timelineNothing. The timeline is the {{timeline}} widget, configured by its own parameters
priority, visible, layerGroup, startOpen, startOpenedOn a groupOrdering and initial stateNothing at group level. priority and visibility are layer properties; openGroup is the group one
popupTemplate, popupCallbackOn a file (vector) layerA popup with the clicked feature’s attributesNothing. They are accepted and never read - no popup opens. Show the attributes from onClick, e.g. with ExtjsUtils.ALERTIFY.log
selectSourceAnywhereChoose a source per layer nameNothing. No part of the platform reads it

3. Accepted, but not honoured

Different case: the platform takes the value, and then does not do what the name promises.

ParameterReality
{{loadcsv\|trim=true}}The flag is passed to the CSV parser, which never reads it. Trim the cells yourself when you use them
maxQntEntries on a calculated layerStored, and clamped to the palette size, but the legend grouping uses its own default instead. To control the entries exactly, build the legend yourself with setCalculateLegend
{{summedarea}} input valueNever filled. The sums reach runOnClick, not inputs.id[ID]
{{hoverpixel}}Moving or clicking never recalculates the layer. Its lastInfo value is always current, so read it in a callback — or force a recalculation yourself
onClickViewGroup / onToggleViewGroup on a layerThey only fire for a real group row (a viewTitle node). On a layer that is not inside a group, they bind to the invisible root and never run

4. Embedding

MistakeEffect
noopener or noreferrer on the iframe or the opened windowMessages between the parent and the map stop working
Re-using an iframe after tearing the connection down, without setting src againThe parent-side helper is gone; the map never answers
Treating one integration’s operation names as platform APIOperation names are a contract between one parent page and one query, not a platform feature

5. Data

MistakeEffect
GeoJSON without a crs (and no fromProj on the layer)The data is assumed to be in the platform’s default projection, and silently lands in the wrong place
Coordinates in latitude/longitude order where the format wants longitude/latitudeFeatures appear mirrored around the diagonal, or off the map
A CSV whose numeric column arrives as textComparisons in expression behave like string comparisons; convert before comparing

6. Style

Two habits worth dropping:

  • A full setup chain on every query. [{ name: "…" }] is a complete query. Add setOptions, decorate, setQueryGlobalProperties only where the map needs them.
  • Code hidden in a made-up decorate key. Any key that decorate does not know is installed as a CSS rule, so writing noTop: (function () { … })() “works” — the function runs while the object is being built, and its return value becomes a stylesheet entry. Use run for code and keep decorate for chrome.

7. Layers age

The most frequent cause of an old query breaking is not the query: a published map was renamed or withdrawn, and the layer that referenced it now resolves to nothing. When reviving an old map, check its layer names against the current catalogue before looking for anything else.

Generated API entries for this chapter

Every property and function named here is listed, with its type, default and example, in the generated API reference: