From b66f511658840a17d8c8620a00115e10f5aada73 Mon Sep 17 00:00:00 2001 From: Anant Jain Date: Mon, 12 Oct 2026 21:38:32 +0530 Subject: [PATCH] fix(api): stop returning exception text from metadata export The export view caught every ValueError around export_dataset() and sent str(exc) back with a 400, so internal errors (crosswalk, dates, rdflib) reached anonymous users verbatim and were reported as client errors. Validate standard and format against export_options() before exporting and answer with a fixed message plus the options. Every other failure now falls to the logged generic 500. Closes #240 --- api/views/metadata_export.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/api/views/metadata_export.py b/api/views/metadata_export.py index a3df43cb..bb7bf5c3 100644 --- a/api/views/metadata_export.py +++ b/api/views/metadata_export.py @@ -43,11 +43,18 @@ def metadata_export(request: HttpRequest, dataset_id: uuid.UUID) -> HttpResponse standard = (request.GET.get("standard") or "dcat").strip().lower() fmt = (request.GET.get("format") or "jsonld").strip().lower() + # Only these two inputs are the caller's fault. Fixed messages: never echo + # an exception to a public client. + options = export_options() + if standard not in options: + return JsonResponse({"error": "Unknown standard", "options": options}, status=400) + if fmt not in options[standard]["formats"]: + return JsonResponse( + {"error": "Format not available for this standard", "options": options}, status=400 + ) try: body, content_type, ext, report = export_dataset(dataset, standard, fmt) - except ValueError as exc: - return JsonResponse({"error": str(exc), "options": export_options()}, status=400) - except Exception as exc: # pragma: no cover - defensive; never 500 on a public page + except Exception as exc: # internal failure: log it, return a fixed message logger.error( "metadata_export_failed", dataset_id=str(dataset_id), standard=standard, error=str(exc) )