)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"71c81c6e7b892ca6d2a056102f03459bbcbe006f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"2af291ba_9e5d985e","updated":"2026-10-01 04:13:32.000000000","message":"lgtm!","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"c69d2b954134e19abd6064c13146ea576e949418","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"189444c4_0640e630","updated":"2026-10-01 08:29:21.000000000","message":"lgtm, good find and thanks for fixing it!","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"b6fa41c3a66bad9760379426d164e9eae07be873","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"1f705543_ada6b0e8","updated":"2026-10-01 19:04:46.000000000","message":"thanks this looks good, \ni have one slight hesitations, should this have a release note?\n\ni dont think its strictly required but just said i would ask incase other think it should, there si a very minor upgrade impact depending on how you used the error message before given the message has changed shape via the removal of the double serisalistion.\n\nif there is no other concern raised ill proceed with this next week.","commit_id":"62279db2636b138ff9c631e58a99c13d0e8d0804"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"557af9ce9fe800d3224c4f5c3bd378a8cff7b7fc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"b7d16c26_89b87f26","in_reply_to":"1f705543_ada6b0e8","updated":"2026-10-01 20:32:58.000000000","message":"Sure, let\u0027s do a release note.","commit_id":"62279db2636b138ff9c631e58a99c13d0e8d0804"}],"cyborg/api/middleware/parsable_error.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ade38a574389f3669bb2df64bda24c2fe6d2c317","unresolved":true,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        app_iter \u003d self.app(environ, replacement_start_response)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"        if (state[\u0027status_code\u0027] // 100) not in (2, 3):"},{"line_number":65,"context_line":"            app_iter \u003d [i.decode(\u0027utf-8\u0027) for i in app_iter]"},{"line_number":66,"context_line":"            err_message \u003d \u0027\\n\u0027.join(app_iter)"},{"line_number":67,"context_line":"            try:"},{"line_number":68,"context_line":"                # WSME encodes error bodies as JSON before they reach here;"},{"line_number":69,"context_line":"                # decode first to avoid double-encoding in dumps()."}],"source_content_type":"text/x-python","patch_set":2,"id":"ee9c5cf5_13be21f6","line":66,"range":{"start_line":64,"start_character":0,"end_line":66,"end_character":45},"updated":"2026-10-01 10:45:23.000000000","message":"so this is setting off my performance spidy senses.\n\n\n```suggestion\n        if (state[\u0027status_code\u0027] // 100) not in (2, 3):\n            raw_body \u003d b\u0027\u0027.join(app_iter)\n            err_message \u003d raw_body.decode(\u0027utf-8\u0027)\n```\n\nwoudl be a lot more effeicne calling decode is expensive in a loop and its a lot cheaper to do it on the concatenated byte string once","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"bb876ffa3285afbe4009c0ac2a26e4457241d1c8","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        app_iter \u003d self.app(environ, replacement_start_response)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"        if (state[\u0027status_code\u0027] // 100) not in (2, 3):"},{"line_number":65,"context_line":"            app_iter \u003d [i.decode(\u0027utf-8\u0027) for i in app_iter]"},{"line_number":66,"context_line":"            err_message \u003d \u0027\\n\u0027.join(app_iter)"},{"line_number":67,"context_line":"            try:"},{"line_number":68,"context_line":"                # WSME encodes error bodies as JSON before they reach here;"},{"line_number":69,"context_line":"                # decode first to avoid double-encoding in dumps()."}],"source_content_type":"text/x-python","patch_set":2,"id":"c95867ae_7a555d1e","line":66,"range":{"start_line":64,"start_character":0,"end_line":66,"end_character":45},"in_reply_to":"ee9c5cf5_13be21f6","updated":"2026-10-01 16:32:21.000000000","message":"Fair point, done.","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"71c81c6e7b892ca6d2a056102f03459bbcbe006f","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            app_iter \u003d [i.decode(\u0027utf-8\u0027) for i in app_iter]"},{"line_number":66,"context_line":"            err_message \u003d \u0027\\n\u0027.join(app_iter)"},{"line_number":67,"context_line":"            try:"},{"line_number":68,"context_line":"                # WSME encodes error bodies as JSON before they reach here;"},{"line_number":69,"context_line":"                # decode first to avoid double-encoding in dumps()."},{"line_number":70,"context_line":"                err_message \u003d jsonutils.loads(err_message)"},{"line_number":71,"context_line":"            except ValueError:"},{"line_number":72,"context_line":"                pass"}],"source_content_type":"text/x-python","patch_set":2,"id":"c730a563_717bc010","line":69,"range":{"start_line":68,"start_character":16,"end_line":69,"end_character":67},"updated":"2026-10-01 04:13:32.000000000","message":"+1 for adding comments!","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ade38a574389f3669bb2df64bda24c2fe6d2c317","unresolved":true,"context_lines":[{"line_number":64,"context_line":"        if (state[\u0027status_code\u0027] // 100) not in (2, 3):"},{"line_number":65,"context_line":"            app_iter \u003d [i.decode(\u0027utf-8\u0027) for i in app_iter]"},{"line_number":66,"context_line":"            err_message \u003d \u0027\\n\u0027.join(app_iter)"},{"line_number":67,"context_line":"            try:"},{"line_number":68,"context_line":"                # WSME encodes error bodies as JSON before they reach here;"},{"line_number":69,"context_line":"                # decode first to avoid double-encoding in dumps()."},{"line_number":70,"context_line":"                err_message \u003d jsonutils.loads(err_message)"},{"line_number":71,"context_line":"            except ValueError:"},{"line_number":72,"context_line":"                pass"},{"line_number":73,"context_line":"            body \u003d [jsonutils.dumps({\u0027error_message\u0027: err_message})]"},{"line_number":74,"context_line":"            body \u003d [i.encode(\u0027utf-8\u0027) for i in body]"},{"line_number":75,"context_line":"            state[\u0027headers\u0027].append((\u0027Content-Type\u0027, \u0027application/json\u0027))"}],"source_content_type":"text/x-python","patch_set":2,"id":"19aacbe0_34b1213d","line":72,"range":{"start_line":67,"start_character":11,"end_line":72,"end_character":20},"updated":"2026-10-01 10:45:23.000000000","message":"I also don\u0027t really like relying on `json.loads()` failing to determine whether the response body contains JSON.\n\nCan we use the original `Content-Type` instead? If the body has already been serialized as JSON at this point, I would expect the response to have an appropriate JSON media type such as `application/json` (or an `application/*+json` type). If it does not, that seems like a bug in the producer of the response.\n\nUsing the content type would avoid attempting to deserialize arbitrary non-JSON error bodies and using a `ValueError` as control flow. It also avoids changing the semantics of plain-text bodies that happen to also be valid JSON values, such as `null`, `true`, or `123`.\n\nIdeally this serialization would happen in a top-level exception handler before reaching this middleware, but that is a larger architectural change and probably outside the scope of this patch.\n\nsomething like this\n```\ncontent_type \u003d state.get(\u0027content_type\u0027, \u0027\u0027)\nmedia_type \u003d content_type.split(\u0027;\u0027, 1)[0].strip().lower()\n\nif media_type \u003d\u003d \u0027application/json\u0027 or media_type.endswith(\u0027+json\u0027):\n    err_message \u003d jsonutils.loads(err_message)\n```","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"bb876ffa3285afbe4009c0ac2a26e4457241d1c8","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        if (state[\u0027status_code\u0027] // 100) not in (2, 3):"},{"line_number":65,"context_line":"            app_iter \u003d [i.decode(\u0027utf-8\u0027) for i in app_iter]"},{"line_number":66,"context_line":"            err_message \u003d \u0027\\n\u0027.join(app_iter)"},{"line_number":67,"context_line":"            try:"},{"line_number":68,"context_line":"                # WSME encodes error bodies as JSON before they reach here;"},{"line_number":69,"context_line":"                # decode first to avoid double-encoding in dumps()."},{"line_number":70,"context_line":"                err_message \u003d jsonutils.loads(err_message)"},{"line_number":71,"context_line":"            except ValueError:"},{"line_number":72,"context_line":"                pass"},{"line_number":73,"context_line":"            body \u003d [jsonutils.dumps({\u0027error_message\u0027: err_message})]"},{"line_number":74,"context_line":"            body \u003d [i.encode(\u0027utf-8\u0027) for i in body]"},{"line_number":75,"context_line":"            state[\u0027headers\u0027].append((\u0027Content-Type\u0027, \u0027application/json\u0027))"}],"source_content_type":"text/x-python","patch_set":2,"id":"f9fcd59f_5de7f9ac","line":72,"range":{"start_line":67,"start_character":11,"end_line":72,"end_character":20},"in_reply_to":"19aacbe0_34b1213d","updated":"2026-10-01 16:32:21.000000000","message":"Heh, I went back and forth whether to do it the way you suggest for the same reason. This seemed more \"Pythonic\" somehow. Updated.","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ade38a574389f3669bb2df64bda24c2fe6d2c317","unresolved":true,"context_lines":[{"line_number":70,"context_line":"                err_message \u003d jsonutils.loads(err_message)"},{"line_number":71,"context_line":"            except ValueError:"},{"line_number":72,"context_line":"                pass"},{"line_number":73,"context_line":"            body \u003d [jsonutils.dumps({\u0027error_message\u0027: err_message})]"},{"line_number":74,"context_line":"            body \u003d [i.encode(\u0027utf-8\u0027) for i in body]"},{"line_number":75,"context_line":"            state[\u0027headers\u0027].append((\u0027Content-Type\u0027, \u0027application/json\u0027))"},{"line_number":76,"context_line":"            state[\u0027headers\u0027].append((\u0027Content-Length\u0027, str(len(body[0]))))"},{"line_number":77,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"9e75fa96_6314f088","line":74,"range":{"start_line":73,"start_character":12,"end_line":74,"end_character":52},"updated":"2026-10-01 10:45:23.000000000","message":"encode is equally expsienive so doing it per cuhnk like that is not a good idea\n\n\n\n```suggestion\n            body \u003d [\n                jsonutils.dumps({\u0027error_message\u0027: err_message}).encode(\u0027utf-8\u0027)]\n```","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"bb876ffa3285afbe4009c0ac2a26e4457241d1c8","unresolved":false,"context_lines":[{"line_number":70,"context_line":"                err_message \u003d jsonutils.loads(err_message)"},{"line_number":71,"context_line":"            except ValueError:"},{"line_number":72,"context_line":"                pass"},{"line_number":73,"context_line":"            body \u003d [jsonutils.dumps({\u0027error_message\u0027: err_message})]"},{"line_number":74,"context_line":"            body \u003d [i.encode(\u0027utf-8\u0027) for i in body]"},{"line_number":75,"context_line":"            state[\u0027headers\u0027].append((\u0027Content-Type\u0027, \u0027application/json\u0027))"},{"line_number":76,"context_line":"            state[\u0027headers\u0027].append((\u0027Content-Length\u0027, str(len(body[0]))))"},{"line_number":77,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7be2308e_37f62c4d","line":74,"range":{"start_line":73,"start_character":12,"end_line":74,"end_character":52},"in_reply_to":"9e75fa96_6314f088","updated":"2026-10-01 16:32:21.000000000","message":"Done","commit_id":"430c61f66ad6a484199d8779bbd0cd63b26f9a91"}]}
