Skip to content

Prevent single error from breaking sharelinks - #7943

Open
ljowen wants to merge 2 commits into
mainfrom
resilient-init-data
Open

ljowen wants to merge 2 commits into
mainfrom
resilient-init-data

Conversation

@ljowen

@ljowen ljowen commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Fixes #5168.

Description

A share link that refers to one broken layer loads nothing - none of the good layers, and the map never moves to the shared location.

Terria._applyInitData already collects most errors and carries on, but a handful of paths still throw part-way through, which abandons every part of the init data after them (workbench, timeline, picked features, ...):

  • loadModelStratum throws "Invalid model traits" when models[id] isn't an object - the throw escapes the Promise.all in _applyInitData and takes down the whole init source.
  • loadModelStratum throws "Model cannot be dereferenced" when the share data has a dereferenced block but the model is no longer a Reference. This is the common real-world case: an item whose type is no longer registered (removed plugin, renamed type) falls back to a stub, and the stub can't be dereferenced. It also escapes the recursive calls for containers and SplitItemReference.
  • An invalid initialCamera or homeCamera throws out of CameraView.fromJson before the workbench is populated.

What this PR does

  • loadModelStratum returns/collects those two errors instead of throwing, and guards container loading so one broken container can't take out the models around it.
  • _applyInitData runs each independent part through a small error-collecting helper (applyPart / applyPartAsync), so one bad part never aborts the rest. The sync helper is deliberately not async, so the MobX @action semantics before the first await are unchanged.
  • loadPickedFeatures no longer leaves a floating promise.

The contract is unchanged: the combined TerriaError is still thrown at the end, so the user still gets a warning naming what failed - the map just loads everything it can first.

Test it

Each link puts two inline-GeoJSON markers on Sydney Harbour (green Opera House, blue Harbour Bridge) with an initialCamera over the harbour, plus one broken thing. Compare the same share link on main and on this branch:

scenario what's broken on main on this branch
broken layer a layer with type: "a-catalog-type-that-no-longer-exists" and a dereferenced block - what a share of a reference item looks like once its type is gone nothing loads both good layers load
invalid initialCamera initialCamera: { "west": "this is not a number" } - the original report: nothing loads and the map never moves nothing loads, camera not applied both good layers load
non-object model traits a model whose traits are a string instead of an object nothing loads both good layers load

The "on this branch" links need this branch's CI deployment to finish. Swap the base for http://localhost:3001/ to run them locally.

Specs

Seven new specs in TerriaSpec under applyInitData -> is resilient to broken init data: a control (nothing broken), non-object model traits, dereferenced on a non-reference model, a broken container, invalid initialCamera, invalid homeCamera, and init data applied after a broken model. All fail on main except the control.

Applying init data threw part-way through on several paths, which
abandoned everything after them - so a share link with one broken layer
loaded no layers at all and never moved the camera.

- loadModelStratum: "Invalid model traits" now returns an error Result
  and "Model cannot be dereferenced" is collected, instead of throwing.
  Loading a container is also guarded so a broken container can't take
  out the models around it.
- _applyInitData: each independent part (catalog, elements, stories,
  viewerMode, baseMaps, homeCamera, initialCamera, splitter, settings,
  each model, previewedItemId, workbench, timeline, pickedFeatures,
  shortenShareUrls) now runs through an error-collecting helper.
- loadPickedFeatures no longer leaves a floating promise.

Errors are still combined and thrown at the end, so the user is warned
about what failed - the map just loads everything it can first.

Fixes #5168
@ljowen ljowen changed the title Don't abandon a share link when one part of it is broken Prevent single error from breaking sharelinks Sep 14, 2026
- Don't raise picked feature load failures to the user. Leaflet rejects
  `allFeaturesAvailablePromise` by design and the failure is already
  surfaced via `pickedFeatures.error`, so a share link with picked
  features and one failing GetFeatureInfo request popped a modal on load.
  Log to the error service instead.
- Return the base map promise from `_applyInitData` even when parts
  failed. It was returned after the throw, so any error dropped it and
  let `loadPersistedOrInitBaseMap()` race the base map set from init
  data. `_applyInitData` now returns the combined error rather than
  throwing it, and callers rethrow.
- Make the workbench part resilient item by item. The whole block -
  model lookup, loading, analytics and the final assignment - was inside
  one `applyPart`, so a single throw dropped every workbench item,
  including the ones that loaded. Items are now collected outside the
  part and committed unconditionally.

`applyPart`/`applyPartAsync` now forward the result of `apply`, which
keeps the per-item guards readable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zoran995 (+ @ljowen ) now that we're touching Terria.ts again, WDYT with breaking out init data parsing out? terria.ts is a 2.5k line file now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me, maybe that should happen as part of the config change @zoran995 is working through

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.

shared links fail spectacularly when a single layer is broken

2 participants