{"record":{"id":"bd2e8354bd949684","repo":"langchain-ai/deepagents","slug":"marketplace-url-must-return-a-json-object-redac","errorCode":null,"errorMessage":"Marketplace URL must return a JSON object: {_redact_url_credentials(url)}","messagePattern":"Marketplace URL must return a JSON object: (.+?)","errorType":"exception","errorClass":"MarketplaceError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/plugins/marketplace.py","lineNumber":389,"sourceCode":"    try:\n        with opener.open(request, timeout=10) as response:\n            final_url = response.geturl()\n            if urlparse(final_url).scheme != \"https\":\n                detail = _redact_url_credentials(final_url)\n                msg = f\"Marketplace response must use https: {detail}\"\n                raise MarketplaceError(msg)\n            data = json.load(response)\n    except (OSError, urllib.error.URLError, json.JSONDecodeError) as exc:\n        msg = (\n            \"Failed to download marketplace from \"\n            f\"{_redact_url_credentials(url)}: {redact_urls_in_text(str(exc))}\"\n        )\n        raise MarketplaceError(msg) from exc\n    if not isinstance(data, dict):\n        msg = (\n            f\"Marketplace URL must return a JSON object: {_redact_url_credentials(url)}\"\n        )\n        raise MarketplaceError(msg)\n    cache_path.parent.mkdir(parents=True, exist_ok=True)\n    cache_path.write_text(\n        json.dumps(data, indent=2, sort_keys=True) + \"\\n\", encoding=\"utf-8\"\n    )\n    return cache_path\n\n\ndef materialize_marketplace_source(\n    source: MarketplaceSource,\n) -> tuple[PluginMarketplace, Path]:\n    \"\"\"Load a marketplace source and return its local install location.\n\n    Args:\n        source: Parsed marketplace source.\n\n    Returns:\n        Parsed marketplace and its local install location.\n","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/plugins/marketplace.py#L371-L407","documentation":"The marketplace catalog downloaded from a URL must be a JSON object (dict) at the top level. If the server returns an array, string, number, or null, the library raises this error because the catalog schema expects keyed fields.","triggerScenarios":"_download_marketplace successfully fetched and parsed the response, but json.load produced a non-dict value — e.g. a top-level JSON array or scalar.","commonSituations":"Serving a plain list of plugins instead of the full catalog object; pointing the URL at an endpoint that returns a different JSON shape (API metadata, health check); a marketplace file exported in the wrong format.","solutions":["Make the endpoint return a top-level JSON object matching the marketplace schema ({\"plugins\": [...] , ...})","Point the URL at the actual catalog file rather than an API or index endpoint","Wrap the data: if you currently return [ ... ], return {\"plugins\": [ ... ]} per the expected schema"],"exampleFix":"// before\n[ {\"name\": \"foo\"} ]\n// after\n{\n  \"plugins\": [ {\"name\": \"foo\"} ]\n}","handlingStrategy":"validation","validationCode":"import urllib.request, json\nwith urllib.request.urlopen(marketplace_url) as r:\n    data = json.load(r)\nif not isinstance(data, dict):\n    raise ValueError(\"marketplace catalog must be a JSON object\")","typeGuard":"from typing import Any\ndef is_marketplace_dict(data: Any) -> bool:\n    return isinstance(data, dict)","tryCatchPattern":"try:\n    marketplace, path = materialize_marketplace_source(source)\nexcept MarketplaceError as exc:\n    if \"must return a JSON object\" in str(exc):\n        log.error(\"Catalog at URL has wrong top-level JSON shape\")\n    raise","preventionTips":["Validate catalogs against the marketplace schema before publishing","Ensure the URL points at the catalog object, not an API index","Never wrap the catalog in a top-level array"],"tags":["json","schema","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}