Bug in 25.04 Websocket API

I’m working on an updated freenas-proxmox zfs over iscsi plugin that uses websockets and I think I ran into a bug in the 25.04 API.

When I run method iscsi.target.query I’m getting the error listed below.

When I run the same query on 24.10.2.1 I get a reasonable response:

[{"alias":"proxmox","id":1,"mode":"ISCSI","groups":[{"authmethod":"NONE","auth":null,"initiator":null,"portal":1}],"auth_networks":[],"rel_tgt_id":1,"name":"proxmox"}]

request:

{"method":"iscsi.target.query","id":3,"msg":"method","jsonrpc":"2.0","params":[[],{}]}

response:

{
    "msg": "result",
    "id": 3,
    "error": {
        "error": 22,
        "errname": "EINVAL",
        "type": null,
        "reason": "'NoneType' object has no attribute 'model_fields'",
        "trace": {
            "class": "AttributeError",
            "frames": [
                {
                    "filename": "/usr/lib/python3/dist-packages/middlewared/apps/websocket_app.py",
                    "lineno": 206,
                    "method": "call_method",
                    "line": "                self.send_error(message, EINVAL, str(e) or repr(e), exc_info())\n",
                    "argspec": [
                        "self",
                        "message",
                        "serviceobj",
                        "methodobj"
                    ],
                    "locals": {
                        "self": "<middlewared.apps.websocket_app.WebSocketApplication object at 0x7f601c65e490>",
                        "message": "{'id': 3, 'msg': 'method', 'params': [[], {}], 'method': 'iscsi.target.query', 'jsonrpc': '2.0'}",
                        "serviceobj": "<middlewared.plugins.iscsi_.targets.iSCSITargetService object at 0x7f603b0926d0>",
                        "methodobj": "<bound method CRUDService.query of <middlewared.plugins.iscsi_.targets.iSCSITargetService object at 0x7f603b0926d0>>",
                        "params": "[[], {}]",
                        "mock": "None",
                        "lam": "<middlewared.api.base.server.legacy_api_method.LegacyAPIMethod object at 0x7f601334f590>",
                        "result": "[{'id': 1, 'name': 'proxmox', 'alias': 'proxmox', 'mode': 'ISCSI', 'auth_networks': ['192.168.11.0/24'], 'rel_tgt_id': 1, 'iscsi_parameters': {}, 'groups': [{'portal': 1, 'initiator': None, 'auth': None, 'authmethod': 'NONE'}]}]",
                        "e": "AttributeError(\"'NoneType' object has no attribute 'model_fields'\")",
                        "adapted": "None"
                    }
                },
                {
                    "filename": "/usr/lib/python3/dist-packages/middlewared/api/base/server/legacy_api_method.py",
                    "lineno": 82,
                    "method": "_dump_result",
                    "line": "            except APIVersionDoesNotContainModelException:\n",
                    "argspec": [
                        "self",
                        "app",
                        "methodobj",
                        "result"
                    ],
                    "locals": {
                        "self": "<middlewared.api.base.server.legacy_api_method.LegacyAPIMethod object at 0x7f601334f590>",
                        "app": "<middlewared.apps.websocket_app.WebSocketApplication object at 0x7f601c65e490>",
                        "methodobj": "<bound method CRUDService.query of <middlewared.plugins.iscsi_.targets.iSCSITargetService object at 0x7f603b0926d0>>",
                        "result": "[{'id': 1, 'name': 'proxmox', 'alias': 'proxmox', 'mode': 'ISCSI', 'auth_networks': ['192.168.11.0/24'], 'rel_tgt_id': 1, 'iscsi_parameters': {}, 'groups': [{'portal': 1, 'initiator': None, 'auth': None, 'authmethod': 'NONE'}]}]",
                        "__class__": "<class 'middlewared.api.base.server.legacy_api_method.LegacyAPIMethod'>"
                    }
                },
                {
                    "filename": "/usr/lib/python3/dist-packages/middlewared/api/base/handler/version.py",
                    "lineno": 126,
                    "method": "adapt_model",
                    "line": "        return model, await value_factory()\n",
                    "argspec": [
                        "self",
                        "value",
                        "model_name",
                        "version1",
                        "version2"
                    ],
                    "locals": {
                        "self": "<middlewared.api.base.handler.version.APIVersionsAdapter object at 0x7f603adfb1d0>",
                        "value": "{'result': [{'id': 1, 'name': 'proxmox', 'alias': 'proxmox', 'mode': 'ISCSI', 'auth_networks': ['192.168.11.0/24'], 'rel_tgt_id': 1, 'iscsi_parameters': {}, 'groups': [{'portal': 1, 'initiator': None, 'auth': None, 'authmethod': 'NONE'}]}]}",
                        "model_name": "'IscsiTargetQueryResult'",
                        "version1": "'v25.04.0'",
                        "version2": "'v24.10'",
                        "version1_index": "1",
                        "version2_index": "0",
                        "current_version": "<APIVersion v24.10>",
                        "current_version_model": "<class 'middlewared.api.v25_04_0.iscsi_target.IscsiTargetQueryResult'>",
                        "value_factory": "functools.partial(<bound method APIVersionsAdapter._adapt_model of <middlewared.api.base.handler.version.APIVersionsAdapter object at 0x7f603adfb1d0>>, functools.partial(<function async_validate_model at 0x7f6071f2f6a0>, <class 'middlewared.api.v25_04_0.iscsi_target.IscsiTargetQueryResult'>, {'result': [{'id': 1, 'name': 'proxmox', 'alias': 'proxmox', 'mode': 'ISCSI', 'auth_networks': ['192.168.11.0/24'], 'rel_tgt_id': 1, 'iscsi_parameters': {}, 'groups': [{'portal': 1, 'initiator': None, 'auth': None, 'authmethod': 'NONE'}]}]}), 'IscsiTargetQueryResult', <APIVersion v25.04.0>, <APIVersion v24.10>, <Direction.DOWNGRADE: 'DOWNGRADE'>)",
                        "model": "None",
                        "step": "-1",
                        "direction": "<Direction.DOWNGRADE: 'DOWNGRADE'>",
                        "version_index": "0",
                        "new_version": "<APIVersion v24.10>"
                    }
                },
                {
                    "filename": "/usr/lib/python3/dist-packages/middlewared/api/base/handler/version.py",
                    "lineno": 146,
                    "method": "_adapt_model",
                    "line": "        return self._adapt_value(await value_factory(), current_model, new_model, direction)\n",
                    "argspec": [
                        "self",
                        "value_factory",
                        "model_name",
                        "current_version",
                        "new_version",
                        "direction"
                    ],
                    "locals": {
                        "self": "<middlewared.api.base.handler.version.APIVersionsAdapter object at 0x7f603adfb1d0>",
                        "value_factory": "functools.partial(<function async_validate_model at 0x7f6071f2f6a0>, <class 'middlewared.api.v25_04_0.iscsi_target.IscsiTargetQueryResult'>, {'result': [{'id': 1, 'name': 'proxmox', 'alias': 'proxmox', 'mode': 'ISCSI', 'auth_networks': ['192.168.11.0/24'], 'rel_tgt_id': 1, 'iscsi_parameters': {}, 'groups': [{'portal': 1, 'initiator': None, 'auth': None, 'authmethod': 'NONE'}]}]})",
                        "model_name": "'IscsiTargetQueryResult'",
                        "current_version": "<APIVersion v25.04.0>",
                        "new_version": "<APIVersion v24.10>",
                        "direction": "<Direction.DOWNGRADE: 'DOWNGRADE'>",
                        "current_model": "<class 'middlewared.api.v25_04_0.iscsi_target.IscsiTargetQueryResult'>",
                        "new_model": "None"
                    }
                },
                {
                    "filename": "/usr/lib/python3/dist-packages/middlewared/api/base/handler/version.py",
                    "lineno": 156,
                    "method": "_adapt_value",
                    "line": "            if k in current_model.model_fields and k in new_model.model_fields:\n",
                    "argspec": [
                        "self",
                        "value",
                        "current_model",
                        "new_model",
                        "direction"
                    ],
                    "locals": {
                        "self": "<middlewared.api.base.handler.version.APIVersionsAdapter object at 0x7f603adfb1d0>",
                        "value": "{'result': [{'id': 1, 'name': 'proxmox', 'alias': 'proxmox', 'mode': 'ISCSI', 'groups': [{'portal': 1, 'initiator': None, 'authmethod': 'NONE', 'auth': None}], 'auth_networks': ['192.168.11.0/24'], 'rel_tgt_id': 1, 'iscsi_parameters': {'QueuedCommands': None}}]}",
                        "current_model": "<class 'middlewared.api.v25_04_0.iscsi_target.IscsiTargetQueryResult'>",
                        "new_model": "None",
                        "direction": "<Direction.DOWNGRADE: 'DOWNGRADE'>",
                        "k": "'result'"
                    }
                }
            ],
            "formatted": "Traceback (most recent call last):\n  File \"/usr/lib/python3/dist-packages/middlewared/apps/websocket_app.py\", line 157, in call_method\n    result = await lam._dump_result(self, methodobj, result)\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/lib/python3/dist-packages/middlewared/api/base/server/legacy_api_method.py\", line 76, in _dump_result\n    model, result = await self.adapter.adapt_model(\n                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/lib/python3/dist-packages/middlewared/api/base/handler/version.py\", line 126, in adapt_model\n    return model, await value_factory()\n                  ^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/lib/python3/dist-packages/middlewared/api/base/handler/version.py\", line 146, in _adapt_model\n    return self._adapt_value(await value_factory(), current_model, new_model, direction)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/lib/python3/dist-packages/middlewared/api/base/handler/version.py\", line 156, in _adapt_value\n    if k in current_model.model_fields and k in new_model.model_fields:\n                                                ^^^^^^^^^^^^^^^^^^^^^^\nAttributeError: 'NoneType' object has no attribute 'model_fields'\n",
            "repr": "AttributeError(\"'NoneType' object has no attribute 'model_fields'\")"
        },
        "extra": null
    }
}
1 Like

Can you file a jira ticket please and upload a debug?

1 Like

I’m new here. Where do I RTFM on how to do that?

1 Like

Done. Thx

1 Like

Thanks!

Here’s the Jira link to NAS-135643, for anyone who wants to track this:
https://ixsystems.atlassian.net/issues/NAS-135643