Fix: Add error handling for missing 'tiles' key in stac_tile response#1282
Fix: Add error handling for missing 'tiles' key in stac_tile response#1282
Conversation
There was a problem hiding this comment.
Pull request overview
Adds defensive handling in stac_tile() when the TiTiler tilejson response does not include a "tiles" key, replacing an unhelpful KeyError with a more descriptive exception.
Changes:
- Detects missing
"tiles"in the TiTiler response before indexing. - Attempts to extract a helpful error message from common error response shapes.
- Raises a
ValueErrorwith details instead of failing withKeyError.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if "tiles" not in r: | ||
| # Try to provide helpful error message from the API response | ||
| if "detail" in r: | ||
| error_msg = f"TiTiler endpoint error: {r['detail']}" |
There was a problem hiding this comment.
The common FastAPI/TiTiler validation error shape is a dict with a "detail" key whose value is a list of error dicts (e.g., {"detail": [{"loc": ..., "msg": ...}]}). In that case this branch will raise ValueError with the raw list repr, and the more user-friendly per-field formatting below is never used. Consider detecting isinstance(r.get('detail'), list) and formatting that list similarly (or delegating to a shared formatter) before falling back to str(r['detail']).
| error_msg = f"TiTiler endpoint error: {r['detail']}" | |
| detail = r.get("detail") | |
| # Common FastAPI/TiTiler shape: {"detail": [{"loc": ..., "msg": ...}, ...]} | |
| if isinstance(detail, list) and len(detail) > 0 and isinstance(detail[0], dict) and "msg" in detail[0]: | |
| errors = [] | |
| for e in detail: | |
| loc = "->".join(str(x) for x in e.get("loc", [])) | |
| msg = e.get("msg", "") | |
| errors.append(f"{loc}: {msg}") | |
| error_msg = f"TiTiler endpoint validation failed: {'; '.join(errors)}" | |
| else: | |
| error_msg = f"TiTiler endpoint error: {detail}" |
|
🚀 Deployed on https://6975bbd5f8d852ae24897b9e--opengeos.netlify.app |
When stac_stats fails for Planetary Computer items, it was overwriting the titiler_endpoint variable with a fallback string endpoint. This caused the subsequent tile request to use the wrong endpoint path (/stac/ instead of /item/), which expects different parameters and returns errors. Changes: 1. Use a separate fallback_endpoint variable for stac_stats fallback 2. Add error handling to check for 'tiles' key before accessing it 3. Provide informative error messages based on API response type Fixes opengeos/geoai#468
5d74ca5 to
ebcb497
Compare
The Planetary Computer /item/info.geojson endpoint returns a GeoJSON Feature
with bounds nested in properties.{asset}.bounds, not a top-level bbox field.
This fix:
- Checks for bounds in properties.{asset}.bounds format
- Falls back to calculating bbox from geometry coordinates
- Ensures map zooms to correct location when visualizing NAIP items
Fixes opengeos/geoai#468
for more information, see https://pre-commit.ci
When stac_stats fails (e.g., for Planetary Computer items that don't support the statistics endpoint), the errors were being printed to stdout, cluttering the output. This fix: - Wraps both primary and fallback stac_stats calls in try-except - Silently continues without rescaling if stats are unavailable - Removes the print(stats['detail']) statement - Sets stats=None if both attempts fail The tile visualization works fine without stats - they're only used for automatic rescaling, which isn't critical for display. Fixes opengeos/geoai#468
The real bug: check_titiler_endpoint was calling .lower() on the endpoint parameter without checking if it was a string first. When stac_stats was called with a PlanetaryComputerEndpoint object, it would pass it through check_titiler_endpoint again, which would fail trying to call .lower() on the object. This caused stac_stats to fail and fall back to the giswqs endpoint, which then printed error messages. The fix: - Check isinstance(titiler_endpoint, str) before calling .lower() - Allow endpoint objects to pass through unchanged - Now stac_stats works correctly with Planetary Computer from the start - No more fallback needed, no more error messages - Stats are properly retrieved and used for automatic rescaling This is the proper fix instead of just silencing errors. Fixes opengeos/geoai#468
…#1282) * Fix: Prevent titiler_endpoint from being overwritten in stac_tile When stac_stats fails for Planetary Computer items, it was overwriting the titiler_endpoint variable with a fallback string endpoint. This caused the subsequent tile request to use the wrong endpoint path (/stac/ instead of /item/), which expects different parameters and returns errors. Changes: 1. Use a separate fallback_endpoint variable for stac_stats fallback 2. Add error handling to check for 'tiles' key before accessing it 3. Provide informative error messages based on API response type Fixes opengeos/geoai#468 * Fix stac_bounds to handle GeoJSON Feature format from Planetary Computer The Planetary Computer /item/info.geojson endpoint returns a GeoJSON Feature with bounds nested in properties.{asset}.bounds, not a top-level bbox field. This fix: - Checks for bounds in properties.{asset}.bounds format - Falls back to calculating bbox from geometry coordinates - Ensures map zooms to correct location when visualizing NAIP items Fixes opengeos/geoai#468 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Silently handle stac_stats failures instead of printing errors When stac_stats fails (e.g., for Planetary Computer items that don't support the statistics endpoint), the errors were being printed to stdout, cluttering the output. This fix: - Wraps both primary and fallback stac_stats calls in try-except - Silently continues without rescaling if stats are unavailable - Removes the print(stats['detail']) statement - Sets stats=None if both attempts fail The tile visualization works fine without stats - they're only used for automatic rescaling, which isn't critical for display. Fixes opengeos/geoai#468 * Fix check_titiler_endpoint to handle endpoint objects properly The real bug: check_titiler_endpoint was calling .lower() on the endpoint parameter without checking if it was a string first. When stac_stats was called with a PlanetaryComputerEndpoint object, it would pass it through check_titiler_endpoint again, which would fail trying to call .lower() on the object. This caused stac_stats to fail and fall back to the giswqs endpoint, which then printed error messages. The fix: - Check isinstance(titiler_endpoint, str) before calling .lower() - Allow endpoint objects to pass through unchanged - Now stac_stats works correctly with Planetary Computer from the start - No more fallback needed, no more error messages - Stats are properly retrieved and used for automatic rescaling This is the proper fix instead of just silencing errors. Fixes opengeos/geoai#468 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Description
The NAIP imagery notebook was failing with
KeyError: 'tiles'when trying to visualize search results. This was caused by two issues:Root cause: When
stac_statsfails for Planetary Computer items, it was overwriting thetitiler_endpointvariable with a fallback string endpoint. This caused the subsequent tile request to use the wrong endpoint path (/stac/instead of/item/), which expects aurlparameter instead ofcollection+itemparameters.Symptom: When the wrong endpoint returned an error response, the code tried to access
r['tiles'][0]without checking if thetileskey existed, resulting in an unhelpful KeyError.Changes
fallback_endpointvariable for thestac_statsfallback, preserving the originaltitiler_endpointfor the main tile requestTesting
Tested with the geo conda environment using:
stac_tilecalls with Planetary Computer NAIP itemsExample
Before:
After:
Related Issues
Fixes opengeos/geoai#468