Repository: CS-SI/eodag

Issue:
AttributeError: 'FieldInfo' object has no attribute 'asdict' when looking for `sentinel-1-rtc` in `planetary_computer`
**Describe the bug**
AttributeError: 'FieldInfo' object has no attribute 'asdict' when looking for `sentinel-1-rtc` in `planetary_computer`

**Code To Reproduce**

```py
import os
from eodag import EODataAccessGateway, setup_logging

os.environ["EODAG__PLANETARY_COMPUTER__AUTH__CREDENTIALS__API_KEY"] = "xxx"
os.environ["EODAG_PROVIDERS_WHITELIST"] = "planetary_computer"

if __name__ == "__main__":
    setup_logging(3)  # DEBUG level

    # Create gateway
    dag = EODataAccessGateway()
    dag.set_preferred_provider("planetary_computer")

    # Query all
    products = dag.search_all(
        start='2021-02-10T00:00:00',
        end='2021-02-15T00:00:00',
        geom='POLYGON ((-0.957009651999954 43.624143975, -1.21432507 43.6304504720001, -1.21265838699998 43.6866459940001, -0.836793908999937 43.8657935370001, -0.776473646999932 43.866692545, -0.776474895999968 43.747621789, -0.957009651999954 43.624143975))',
        collection="sentinel-1-rtc"
    )
```

**Output**
```
2026-04-30 15:49:44,500 eodag.config                     [DEBUG   ] Loading configuration from C:\Users\rbraun\Anaconda3\envs\eodownload\Lib\site-packages\eodag\resources\providers.yml
2026-04-30 15:49:45,040 eodag.plugins.manager            [DEBUG   ] CSWSearch plugin skipped, eodag[csw] or eodag[all] needed
2026-04-30 15:49:45,075 eodag.plugins.manager            [DEBUG   ] EcmwfApi plugin skipped, eodag[ecmwf] or eodag[all] needed
2026-04-30 15:49:45,081 eodag.provider                   [INFO    ] Loading user configuration from: C:\Users\rbraun\.config\eodag\eodag.yml
2026-04-30 15:49:45,097 eodag.provider                   [DEBUG   ] Loading configuration from environment variables
2026-04-30 15:49:45,105 eodag.core                       [INFO    ] Locations configuration loaded from C:\Users\rbraun\.config\eodag\locations.yml
2026-04-30 15:49:45,105 eodag.core                       [INFO    ] unknown collection sentinel-1-rtc
2026-04-30 15:49:45,105 eodag.core                       [DEBUG   ] Fetching external collections sources to find sentinel-1-rtc collection
2026-04-30 15:49:45,105 eodag.config                     [INFO    ] Fetching external collections from https://cs-si.github.io/eodag/eodag/resources/ext_collections.json
2026-04-30 15:49:45,360 eodag.core                       [DEBUG   ] Added 129 collections for planetary_computer
2026-04-30 15:49:45,360 eodag.core                       [DEBUG   ] bad formatted attributes skipped for 129 collection(s) on planetary_computer
2026-04-30 15:49:45,361 eodag.config                     [DEBUG   ] Loading configuration from C:\Users\rbraun\Anaconda3\envs\eodownload\Lib\site-packages\eodag\resources\providers.yml
2026-04-30 15:49:45,456 eodag.core                       [INFO    ] Searching on provider planetary_computer
2026-04-30 15:49:45,488 eodag.search.base                [DEBUG   ] Validate request
2026-04-30 15:49:45,505 eodag.search.qssearch            [INFO    ] Fetching queryables: https://planetarycomputer.microsoft.com/api/stac/v1/search/../collections/sentinel-1-rtc/queryables
2026-04-30 15:49:45,849 eodag.core                       [ERROR   ] Error while searching on provider planetary_computer (ignored):
Traceback (most recent call last):
  File "C:\Users\rbraun\Anaconda3\envs\eodownload\Lib\site-packages\eodag\api\core.py", line 1867, in _do_search
    search_plugin.validate(search_params, prep.auth)
  File "C:\Users\rbraun\Anaconda3\envs\eodownload\Lib\site-packages\eodag\plugins\search\base.py", line 444, in validate
    self.list_queryables(
  File "C:\Users\rbraun\Anaconda3\envs\eodownload\Lib\site-packages\eodag\plugins\search\base.py", line 402, in list_queryables
    queryables = self._get_collection_queryables(collection, alias, filters)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\rbraun\Anaconda3\envs\eodownload\Lib\site-packages\eodag\plugins\search\base.py", line 361, in _get_collection_queryables
    queryables = self.discover_queryables(**{**default_values, **filters}) or {}
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\rbraun\Anaconda3\envs\eodownload\Lib\site-packages\eodag\plugins\search\qssearch.py", line 2296, in discover_queryables
    for attr_k, attr_v in provider_queryable_fieldinfo.asdict()
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'FieldInfo' object has no attribute 'asdict'
```

**Environment:**
 - Python version: `Python 3.11.14`
 - EODAG version: `eodag (Earth Observation Data Access Gateway): version 4.2.0`

Discussion:

Fix (patch):
diff --git a/eodag/plugins/search/qssearch.py b/eodag/plugins/search/qssearch.py
index f47852f11d..9382a8b260 100644
--- a/eodag/plugins/search/qssearch.py
+++ b/eodag/plugins/search/qssearch.py
@@ -2279,15 +2279,25 @@ def discover_queryables(
                             eodag_queryable_type,
                             eodag_queryable_fieldinfo,
                         ) = eodag_queryable_args
-                        if ".Literal[" not in str(provider_queryable_type):
+                        provider_has_literal_type = ".Literal[" in str(
+                            provider_queryable_type
+                        )
+                        if not provider_has_literal_type:
                             # use eodag queryable type if provider one has no constraints
                             field_definition = eodag_queryable_type, field_definition[1]
 
-                        # merge provider and eodag queryables FieldInfo metadata
-                        merged_metadata = (
-                            field_definition[1].metadata
-                            + eodag_queryable_fieldinfo.metadata
-                        )
+                        # merge provider and eodag queryables FieldInfo metadata.
+                        # When the provider type has no Literal constraints we keep only eodag's metadata,
+                        # to avoid propagating provider-side constraints that target a different shape than
+                        # the eodag queryable type (patterns do not apply on parameters that
+                        # are parsed/formatted later).
+                        if provider_has_literal_type:
+                            merged_metadata = (
+                                field_definition[1].metadata
+                                + eodag_queryable_fieldinfo.metadata
+                            )
+                        else:
+                            merged_metadata = list(eodag_queryable_fieldinfo.metadata)
                         # build merged attributes: use provider value if set, otherwise fall back to eodag value
                         merged_attrs = {
                             attr_k: (


Test changes:
diff --git a/tests/context.py b/tests/context.py
index cf966287c2..e371b30d9a 100644
--- a/tests/context.py
+++ b/tests/context.py
@@ -75,7 +75,7 @@
 from eodag.plugins.search.build_search_result import ecmwf_temporal_to_eodag
 from eodag.plugins.search.qssearch import QueryStringSearch
 from eodag.types import model_fields_to_annotated
-from eodag.types.queryables import CommonQueryables, Queryables
+from eodag.types.queryables import CommonQueryables, Queryables, QueryablesDict
 from eodag.utils import (
     DEFAULT_MISSION_START_DATE,
     DEFAULT_SHAPELY_GEOMETRY,
diff --git a/tests/units/test_search_plugins.py b/tests/units/test_search_plugins.py
index d2744ecb5d..30c9359aff 100644
--- a/tests/units/test_search_plugins.py
+++ b/tests/units/test_search_plugins.py
@@ -69,6 +69,7 @@
     NotAvailableError,
     PluginManager,
     PreparedSearch,
+    QueryablesDict,
     QueryStringSearch,
     RequestError,
     TimeOutError,
@@ -2536,6 +2537,67 @@ def test_plugins_search_stacsearch_discover_queryables_merge(self, mock_request)
         self.assertEqual(sp_fi.description, "provider-only param")
         self.assertEqual(sp_fi.title, "Some param")
 
+    @mock.patch(
+        "eodag.plugins.search.qssearch.QueryStringSearch._request", autospec=True
+    )
+    def test_plugins_search_stacsearch_discover_queryables_no_pattern_propagation(
+        self, mock_request
+    ):
+        """discover_queryables must not propagate provider `pattern` or other
+        constraints onto eodag queryables, which are parsed/formatted later.
+        """
+        provider_queryables = {
+            "type": "object",
+            "properties": {
+                # mimics planetary-computer strict ISO UTC pattern
+                "start_datetime": {
+                    "title": "Start datetime",
+                    "type": "string",
+                    "format": "date-time",
+                    "pattern": "(\\+00:00|Z)$",
+                },
+                "end_datetime": {
+                    "title": "End datetime",
+                    "type": "string",
+                    "format": "date-time",
+                    "pattern": "(\\+00:00|Z)$",
+                },
+            },
+        }
+        mock_request.return_value = mock.Mock()
+        mock_request.return_value.json.side_effect = [provider_queryables]
+        plugin = self.get_search_plugin(provider="dedl")
+        queryables = plugin.discover_queryables(
+            collection="CAMS_GAC_FORECAST", provider="dedl"
+        )
+
+        # "start" / "end" must be present and carry no `pattern` metadata
+        for key in ("start", "end"):
+            self.assertIn(key, queryables)
+            field_type, field_info = get_args(queryables[key])[:2]
+            self.assertEqual(field_type, str)
+            patterns = [
+                getattr(m, "pattern", None)
+                for m in field_info.metadata
+                if getattr(m, "pattern", None)
+                and getattr(m, "pattern", None) is not PydanticUndefined
+            ]
+            self.assertEqual(
+                patterns,
+                [],
+                f"unexpected pattern metadata propagated to `{key}`: {patterns}",
+            )
+
+        # build the pydantic model from these queryables and validate
+        model = QueryablesDict(**queryables).get_model()
+        model.model_validate(
+            {
+                "collection": "CAMS_GAC_FORECAST",
+                "start_datetime": "2024-01-01",
+                "end_datetime": "2024-01-31",
+            }
+        )
+
     @mock.patch(
         "eodag.plugins.search.qssearch.QueryStringSearch._request", autospec=True
     )