)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"23856bf6d9274a80194b166e9fdc6072be25c276","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"1f7508cd_6d18e518","updated":"2026-11-06 13:48:08.000000000","message":"Few findings noted inline.","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"3850b14c6bd02e2873262f41cb622f7e501a0735","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"5a30a6f5_2e02fe6d","updated":"2026-11-06 14:07:20.000000000","message":"Will respin","commit_id":"fa12ff7a0b55061543ee65f591f2e6573b9e3884"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"33e111d3449ffc47eb0aedef9ee2386d387ef559","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"8f16d3d1_0206b406","updated":"2026-11-06 15:17:44.000000000","message":"Thank you for addressing the comments, looks better now!!","commit_id":"b92ef705849c44c8093c0d1bad334ad248de0ea2"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"c26f9f8c7847b199690aaccf3aaf10bea09bfbfd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"bb420ca9_adc4bb9c","updated":"2026-11-09 09:33:23.000000000","message":"Turns out JSON error parsing in glanceclient is broken. We need to fix that first.","commit_id":"e72e36bc632aa5ea96c378b7be09b4af5c245575"}],"glance/api/middleware/error_response.py":[{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"23856bf6d9274a80194b166e9fdc6072be25c276","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":2,"context_line":"# not use this file except in compliance with the License. You may obtain"},{"line_number":3,"context_line":"# a copy of the License at"},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":1,"id":"03effbe0_c5097f23","line":1,"updated":"2026-11-06 13:48:08.000000000","message":"Copyright header missing","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"bbe9d9c7576e85b894995ed4a3e02cdddc9c8fa3","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":2,"context_line":"# not use this file except in compliance with the License. You may obtain"},{"line_number":3,"context_line":"# a copy of the License at"},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a531242_f40f6fd7","line":1,"in_reply_to":"03effbe0_c5097f23","updated":"2026-11-06 14:37:54.000000000","message":"Done","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"23856bf6d9274a80194b166e9fdc6072be25c276","unresolved":true,"context_lines":[{"line_number":22,"context_line":"    status codes and headers, including errors from routing and middleware."},{"line_number":23,"context_line":"    \"\"\""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    def process_request(self, req):"},{"line_number":26,"context_line":"        offers \u003d req.accept.acceptable_offers("},{"line_number":27,"context_line":"            (\u0027application/json\u0027, \u0027text/html\u0027, \u0027text/plain\u0027))"},{"line_number":28,"context_line":"        if offers:"},{"line_number":29,"context_line":"            req.accept \u003d offers[0][0]"},{"line_number":30,"context_line":"        elif not req.headers.get(\u0027Accept\u0027):"},{"line_number":31,"context_line":"            req.accept \u003d \u0027application/json\u0027"},{"line_number":32,"context_line":"        # Preserve unsupported media types, particularly Glance\u0027s vendor"},{"line_number":33,"context_line":"        # media types used by version negotiation."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def process_response(self, response):"},{"line_number":36,"context_line":"        # WebOb skips exception content negotiation for HEAD requests."}],"source_content_type":"text/x-python","patch_set":1,"id":"87d6a162_9a08aa66","line":33,"range":{"start_line":25,"start_character":0,"end_line":33,"end_character":50},"updated":"2026-11-06 13:48:08.000000000","message":"This rewrites Accept for every request, not just for errors.","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"8b774f2347785af396434eeef0e7e735d7c81fa0","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    status codes and headers, including errors from routing and middleware."},{"line_number":23,"context_line":"    \"\"\""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    def process_request(self, req):"},{"line_number":26,"context_line":"        offers \u003d req.accept.acceptable_offers("},{"line_number":27,"context_line":"            (\u0027application/json\u0027, \u0027text/html\u0027, \u0027text/plain\u0027))"},{"line_number":28,"context_line":"        if offers:"},{"line_number":29,"context_line":"            req.accept \u003d offers[0][0]"},{"line_number":30,"context_line":"        elif not req.headers.get(\u0027Accept\u0027):"},{"line_number":31,"context_line":"            req.accept \u003d \u0027application/json\u0027"},{"line_number":32,"context_line":"        # Preserve unsupported media types, particularly Glance\u0027s vendor"},{"line_number":33,"context_line":"        # media types used by version negotiation."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def process_response(self, response):"},{"line_number":36,"context_line":"        # WebOb skips exception content negotiation for HEAD requests."}],"source_content_type":"text/x-python","patch_set":1,"id":"f134d78b_3a42c9ea","line":33,"range":{"start_line":25,"start_character":0,"end_line":33,"end_character":50},"in_reply_to":"1a168d1a_dce1fc3f","updated":"2026-11-06 14:53:52.000000000","message":"Okay, I\u0027ve changed my mind on this. Let\u0027s just do what Nova etc. do. If it\u0027s good enough for them, it\u0027s good enough for us.","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"bbe9d9c7576e85b894995ed4a3e02cdddc9c8fa3","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    status codes and headers, including errors from routing and middleware."},{"line_number":23,"context_line":"    \"\"\""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    def process_request(self, req):"},{"line_number":26,"context_line":"        offers \u003d req.accept.acceptable_offers("},{"line_number":27,"context_line":"            (\u0027application/json\u0027, \u0027text/html\u0027, \u0027text/plain\u0027))"},{"line_number":28,"context_line":"        if offers:"},{"line_number":29,"context_line":"            req.accept \u003d offers[0][0]"},{"line_number":30,"context_line":"        elif not req.headers.get(\u0027Accept\u0027):"},{"line_number":31,"context_line":"            req.accept \u003d \u0027application/json\u0027"},{"line_number":32,"context_line":"        # Preserve unsupported media types, particularly Glance\u0027s vendor"},{"line_number":33,"context_line":"        # media types used by version negotiation."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def process_response(self, response):"},{"line_number":36,"context_line":"        # WebOb skips exception content negotiation for HEAD requests."}],"source_content_type":"text/x-python","patch_set":1,"id":"1a168d1a_dce1fc3f","line":33,"range":{"start_line":25,"start_character":0,"end_line":33,"end_character":50},"in_reply_to":"87d6a162_9a08aa66","updated":"2026-11-06 14:37:54.000000000","message":"We discussed this on IRC. Repeating [what I said there](https://meetings.opendev.org/irclogs/%23openstack-glance/%23openstack-glance.2026-11-06.log.html):\n\n\u003e [T]he reason I adopted that approach is that we want to agree on a `Accept` header up front so that it propagates to downstream middleware (e.g. keystonemiddleware). If I don\u0027t do that, all middleware needs to carry similar \"default to JSON if no header given\" behavior\n\nI\u0027ll update the commit message to make this a little more explicit.","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"23856bf6d9274a80194b166e9fdc6072be25c276","unresolved":true,"context_lines":[{"line_number":35,"context_line":"    def process_response(self, response):"},{"line_number":36,"context_line":"        # WebOb skips exception content negotiation for HEAD requests."},{"line_number":37,"context_line":"        # Match the negotiated GET representation without adding a body."},{"line_number":38,"context_line":"        if (response.request.method \u003d\u003d \u0027HEAD\u0027 and"},{"line_number":39,"context_line":"                response.status_int \u003e\u003d 400 and"},{"line_number":40,"context_line":"                response.content_type \u003d\u003d \u0027text/html\u0027 and"},{"line_number":41,"context_line":"                str(response.request.accept) in"},{"line_number":42,"context_line":"                (\u0027application/json\u0027, \u0027text/plain\u0027)):"},{"line_number":43,"context_line":"            response.content_type \u003d str(response.request.accept)"},{"line_number":44,"context_line":"        return response"}],"source_content_type":"text/x-python","patch_set":1,"id":"cbb89b78_b020f17d","line":42,"range":{"start_line":38,"start_character":0,"end_line":42,"end_character":52},"updated":"2026-11-06 13:48:08.000000000","message":"As per documentation unsupported Accept values retain WebOb’s plain-text fallback [api-ref/source/v2/errors.inc line 39] - But HEAD handling only rewrites text/html to JSON/plain when the negotiated value is exactly one of these. IMO for HEAD with Accept: application/xml, the response remains text/html; the equivalent GET returns text/plain.","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"bbe9d9c7576e85b894995ed4a3e02cdddc9c8fa3","unresolved":false,"context_lines":[{"line_number":35,"context_line":"    def process_response(self, response):"},{"line_number":36,"context_line":"        # WebOb skips exception content negotiation for HEAD requests."},{"line_number":37,"context_line":"        # Match the negotiated GET representation without adding a body."},{"line_number":38,"context_line":"        if (response.request.method \u003d\u003d \u0027HEAD\u0027 and"},{"line_number":39,"context_line":"                response.status_int \u003e\u003d 400 and"},{"line_number":40,"context_line":"                response.content_type \u003d\u003d \u0027text/html\u0027 and"},{"line_number":41,"context_line":"                str(response.request.accept) in"},{"line_number":42,"context_line":"                (\u0027application/json\u0027, \u0027text/plain\u0027)):"},{"line_number":43,"context_line":"            response.content_type \u003d str(response.request.accept)"},{"line_number":44,"context_line":"        return response"}],"source_content_type":"text/x-python","patch_set":1,"id":"48eba03e_3b510648","line":42,"range":{"start_line":38,"start_character":0,"end_line":42,"end_character":52},"in_reply_to":"cbb89b78_b020f17d","updated":"2026-11-06 14:37:54.000000000","message":"Oh, that\u0027s a good catch 😅 Fixed.","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"}],"glance/tests/unit/api/middleware/test_error_response.py":[{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"23856bf6d9274a80194b166e9fdc6072be25c276","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":2,"context_line":"# not use this file except in compliance with the License. You may obtain"},{"line_number":3,"context_line":"# a copy of the License at"},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":1,"id":"02b9934d_0ef9a5f2","line":1,"updated":"2026-11-06 13:48:08.000000000","message":"ditto","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"bbe9d9c7576e85b894995ed4a3e02cdddc9c8fa3","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":2,"context_line":"# not use this file except in compliance with the License. You may obtain"},{"line_number":3,"context_line":"# a copy of the License at"},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":1,"id":"a23b9cc6_0fa1ae63","line":1,"in_reply_to":"02b9934d_0ef9a5f2","updated":"2026-11-06 14:37:54.000000000","message":"Done","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"}],"releasenotes/notes/json-error-responses-8e5f2a6d924b03c1.yaml":[{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"23856bf6d9274a80194b166e9fdc6072be25c276","unresolved":true,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"fixes:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Glance now defaults to JSON for HTTP error responses when the client"},{"line_number":5,"context_line":"    omits the ``Accept`` header or accepts any media type (``*/*``), matching"}],"source_content_type":"text/x-yaml","patch_set":1,"id":"dfb8f29d_194817ae","line":2,"range":{"start_line":2,"start_character":0,"end_line":2,"end_character":5},"updated":"2026-11-06 13:48:08.000000000","message":"I think this should be different title, may be features?","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"bbe9d9c7576e85b894995ed4a3e02cdddc9c8fa3","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"fixes:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Glance now defaults to JSON for HTTP error responses when the client"},{"line_number":5,"context_line":"    omits the ``Accept`` header or accepts any media type (``*/*``), matching"}],"source_content_type":"text/x-yaml","patch_set":1,"id":"93ab7a8a_f354dd42","line":2,"range":{"start_line":2,"start_character":0,"end_line":2,"end_character":5},"in_reply_to":"dfb8f29d_194817ae","updated":"2026-11-06 14:37:54.000000000","message":"Fair","commit_id":"5850d6c9c069dac8a57ac40784a22046fbf9b22b"}]}
