diff --git a/backend/backend/settings/base.py b/backend/backend/settings/base.py index 7593305fdd..970b5fac6a 100644 --- a/backend/backend/settings/base.py +++ b/backend/backend/settings/base.py @@ -15,10 +15,17 @@ from urllib.parse import quote import httpx +from django.core.validators import URLValidator from dotenv import find_dotenv, load_dotenv from utils.common_utils import CommonUtils from utils.cors_origin import normalize_web_app_origin +# Django 5.0+ caps URLValidator at 2048 chars. S3 pre-signed URLs signed with +# temporary/STS credentials (carrying X-Amz-Security-Token) routinely exceed this, +# causing "Enter a valid URL." on the API deployment `presigned_urls` field. +# Raise the cap globally. No-op on Django 4.2.x (no such attribute is checked). +URLValidator.max_length = 8192 + missing_settings = [] diff --git a/workers/executor/executors/legacy_executor.py b/workers/executor/executors/legacy_executor.py index eae4d05b2f..ce7fbea0d1 100644 --- a/workers/executor/executors/legacy_executor.py +++ b/workers/executor/executors/legacy_executor.py @@ -703,6 +703,19 @@ def _failure(child_result: ExecutionResult) -> ExecutionResult: ) output_map = structured_output.get(PSKeys.OUTPUT, {}) or {} + if not isinstance(output_map, dict): + # Single-pass can return a non-dict (e.g. a top-level JSON array) when the + # LLM emits a truncated/runaway response. Fail clearly instead of crashing + # on .values(), and keep the malformed shape from flowing downstream as a + # success. + return ExecutionResult.failure( + error=( + f"Single-pass extraction returned a {type(output_map).__name__}, " + "expected a field map; the LLM likely produced a truncated or " + "runaway response (check output-token usage)." + ), + metadata={"usage_records": pipeline_records}, + ) answered = sum(1 for v in output_map.values() if v not in (None, "", [], {})) shim.stream_log(f"Pipeline completed: {answered}/{len(outputs)} prompts answered") out_metadata = {