# Buggy code
def keypress(self, xxx_todo_changeme, key):
    (maxcol,) = xxx_todo_changeme
    key = common.shortcuts(key)
    if key == "a":
        self.flow.accept_intercept(self.master)
        signals.flowlist_change.send(self)
    elif key == "d":
        if self.flow.killable:
            self.flow.kill(self.master)
        self.state.delete_flow(self.flow)
        signals.flowlist_change.send(self)
    elif key == "D":
        f = self.master.duplicate_flow(self.flow)
        self.master.state.set_focus_flow(f)
        signals.flowlist_change.send(self)
    elif key == "m":
        self.flow.marked = not self.flow.marked
        signals.flowlist_change.send(self)
    elif key == "M":
        if self.state.mark_filter:
            self.state.disable_marked_filter()
        else:
            self.state.enable_marked_filter()
        signals.flowlist_change.send(self)
    elif key == "r":
        self.master.replay_request(self.flow)
        signals.flowlist_change.send(self)
    elif key == "S":

        def stop_server_playback(response):
            if response == "y":
                self.master.options.server_replay = []

        a = self.master.addons.get("serverplayback")
        if a.count():
            signals.status_prompt_onekey.send(
                prompt="Stop current server replay?",
                keys=(
                    ("yes", "y"),
                    ("no", "n"),
                ),
                callback=stop_server_playback,
            )
        else:
            signals.status_prompt_onekey.send(
                prompt="Server Replay",
                keys=(
                    ("all flows", "a"),
                    ("this flow", "t"),
                ),
                callback=self.server_replay_prompt,
            )
    elif key == "U":
        for f in self.state.flows:
            f.marked = False
        signals.flowlist_change.send(self)
    elif key == "V":
        if not self.flow.modified():
            signals.status_message.send(message="Flow not modified.")
            return
        self.state.revert(self.flow)
        signals.flowlist_change.send(self)
        signals.status_message.send(message="Reverted.")
    elif key == "w":
        signals.status_prompt_onekey.send(
            self,
            prompt="Save",
            keys=(
                ("listed flows", "l"),
                ("this flow", "t"),
            ),
            callback=self.save_flows_prompt,
        )
    elif key == "X":
        if self.flow.killable:
            self.flow.kill(self.master)
    elif key == "enter":
        if self.flow.request:
            self.master.view_flow(self.flow)
    elif key == "|":
        signals.status_prompt_path.send(
            prompt="Send flow to script",
            callback=self.master.run_script_once,
            args=(self.flow,),
        )
    elif key == "E":
        signals.status_prompt_onekey.send(
            self,
            prompt="Export to file",
            keys=[(e[0], e[1]) for e in export.EXPORTERS],
            callback=common.export_to_clip_or_file,
            args=(None, self.flow, common.ask_save_path),
        )
    elif key == "C":
        signals.status_prompt_onekey.send(
            self,
            prompt="Export to clipboard",
            keys=[(e[0], e[1]) for e in export.EXPORTERS],
            callback=common.export_to_clip_or_file,
            args=(None, self.flow, common.copy_to_clipboard_or_prompt),
        )
    elif key == "b":
        common.ask_save_body(None, self.flow)
    else:
        return key


# Traceback (AttributeError)
user@user-ubuntu:~$ mitmproxy
Exception ignored in: <bound method Reply.__del__ of <mitmproxy.controller.Reply object at 0x7f69de8646a0>>
Traceback (most recent call last):
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 269, in __del__
raise exceptions.ControlException("Un-acked message: %s" % self.obj)
mitmproxy.exceptions.ControlException: Un-acked message: <HTTPFlow
request = Request(GET www.example.com:80/)
server_conn = <ServerConnection: www.example.com:80>>
Exception ignored in: <bound method Reply.__del__ of <mitmproxy.controller.Reply object at 0x7f69de864da0>>
Traceback (most recent call last):
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 269, in __del__
raise exceptions.ControlException("Un-acked message: %s" % self.obj)
mitmproxy.exceptions.ControlException: Un-acked message: <HTTPFlow
request = Request(GET www.example.com:80/)
response = Response(200 OK, text/html, 1.24k)
server_conn = <ServerConnection: www.example.com:80>>
rTraceback (most recent call last):
File "/media/sf_git/mitmproxy/mitmproxy/console/master.py", line 502, in run
self.loop.run()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 278, in run
self._run()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 376, in _run
self.event_loop.run()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 682, in run
self._loop()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 715, in _loop
alarm_callback()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 164, in cb
callback(self, user_data)
File "/media/sf_git/mitmproxy/mitmproxy/console/master.py", line 448, in ticker
changed = self.tick(timeout=0)
File "/media/sf_git/mitmproxy/mitmproxy/flow/master.py", line 140, in tick
return super(FlowMaster, self).tick(timeout)
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 136, in tick
handle_func(obj)
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 219, in wrapper
master.addons(f.__name__, message)
File "/media/sf_git/mitmproxy/mitmproxy/addons.py", line 64, in __call__
self.invoke(i, name, *args, **kwargs)
File "/media/sf_git/mitmproxy/mitmproxy/addons.py", line 60, in invoke
func(*args, **kwargs)
File "/media/sf_git/mitmproxy/mitmproxy/builtins/setheaders.py", line 39, in response
self.run(flow, flow.response.headers)
AttributeError: 'NoneType' object has no attribute 'headers'

mitmproxy has crashed!
Please lodge a bug report at:
https://github.com/mitmproxy/mitmproxy
Shutting down...
rrrrrrrrrrException ignored in: <bound method Reply.__del__ of <mitmproxy.controller.Reply object at 0x7f69df0c2c18>>
Traceback (most recent call last):
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 269, in __del__
mitmproxy.exceptions.ControlException: Un-acked message: <HTTPFlow
request = Request(GET www.example.com:80/)
response = Response(200 OK, text/html, 1.24k)
error = Connection killed
server_conn = <ServerConnection: www.example.com:80>>
user@user-ubuntu:~$ mitmproxy
rException ignored in: <bound method Reply.__del__ of <mitmproxy.controller.Reply object at 0x7f17c5270ac8>>
Traceback (most recent call last):
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 269, in __del__
raise exceptions.ControlException("Un-acked message: %s" % self.obj)
mitmproxy.exceptions.ControlException: Un-acked message: <HTTPFlow
request = Request(GET www.example.com:80/)
response = Response(200 OK, text/html, 1.24k)
server_conn = <ServerConnection: www.example.com:80>>
rException ignored in: <bound method Reply.__del__ of <mitmproxy.controller.Reply object at 0x7f17c5291908>>
Traceback (most recent call last):
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 269, in __del__
raise exceptions.ControlException("Un-acked message: %s" % self.obj)
mitmproxy.exceptions.ControlException: Un-acked message: <HTTPFlow
request = Request(GET www.example.com:80/)
response = Response(200 OK, text/html, 1.24k)
server_conn = <ServerConnection: www.example.com:80>>
Traceback (most recent call last):
File "/media/sf_git/mitmproxy/mitmproxy/console/master.py", line 502, in run
self.loop.run()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 278, in run
self._run()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 376, in _run
self.event_loop.run()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 682, in run
self._loop()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 715, in _loop
alarm_callback()
File "/usr/local/lib/python3.5/dist-packages/urwid/main_loop.py", line 164, in cb
callback(self, user_data)
File "/media/sf_git/mitmproxy/mitmproxy/console/master.py", line 448, in ticker
changed = self.tick(timeout=0)
File "/media/sf_git/mitmproxy/mitmproxy/flow/master.py", line 140, in tick
return super(FlowMaster, self).tick(timeout)
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 136, in tick
handle_func(obj)
File "/media/sf_git/mitmproxy/mitmproxy/controller.py", line 219, in wrapper
master.addons(f.__name__, message)
File "/media/sf_git/mitmproxy/mitmproxy/addons.py", line 64, in __call__
self.invoke(i, name, *args, **kwargs)
File "/media/sf_git/mitmproxy/mitmproxy/addons.py", line 60, in invoke
func(*args, **kwargs)
File "/media/sf_git/mitmproxy/mitmproxy/builtins/setheaders.py", line 39, in response
self.run(flow, flow.response.headers)
AttributeError: 'NoneType' object has no attribute 'headers'

mitmproxy has crashed!
Please lodge a bug report at:
https://github.com/mitmproxy/mitmproxy
Shutting down...

# Fixed code
def keypress(self, xxx_todo_changeme, key):
    (maxcol,) = xxx_todo_changeme
    key = common.shortcuts(key)
    if key == "a":
        self.flow.accept_intercept(self.master)
        signals.flowlist_change.send(self)
    elif key == "d":
        if self.flow.killable:
            self.flow.kill(self.master)
        self.state.delete_flow(self.flow)
        signals.flowlist_change.send(self)
    elif key == "D":
        f = self.master.duplicate_flow(self.flow)
        self.master.state.set_focus_flow(f)
        signals.flowlist_change.send(self)
    elif key == "m":
        self.flow.marked = not self.flow.marked
        signals.flowlist_change.send(self)
    elif key == "M":
        if self.state.mark_filter:
            self.state.disable_marked_filter()
        else:
            self.state.enable_marked_filter()
        signals.flowlist_change.send(self)
    elif key == "r":
        try:
            self.master.replay_request(self.flow)
        except exceptions.ReplayException as e:
            signals.add_log("Replay error: %s" % e, "warn")
        signals.flowlist_change.send(self)
    elif key == "S":

        def stop_server_playback(response):
            if response == "y":
                self.master.options.server_replay = []

        a = self.master.addons.get("serverplayback")
        if a.count():
            signals.status_prompt_onekey.send(
                prompt="Stop current server replay?",
                keys=(
                    ("yes", "y"),
                    ("no", "n"),
                ),
                callback=stop_server_playback,
            )
        else:
            signals.status_prompt_onekey.send(
                prompt="Server Replay",
                keys=(
                    ("all flows", "a"),
                    ("this flow", "t"),
                ),
                callback=self.server_replay_prompt,
            )
    elif key == "U":
        for f in self.state.flows:
            f.marked = False
        signals.flowlist_change.send(self)
    elif key == "V":
        if not self.flow.modified():
            signals.status_message.send(message="Flow not modified.")
            return
        self.state.revert(self.flow)
        signals.flowlist_change.send(self)
        signals.status_message.send(message="Reverted.")
    elif key == "w":
        signals.status_prompt_onekey.send(
            self,
            prompt="Save",
            keys=(
                ("listed flows", "l"),
                ("this flow", "t"),
            ),
            callback=self.save_flows_prompt,
        )
    elif key == "X":
        if self.flow.killable:
            self.flow.kill(self.master)
    elif key == "enter":
        if self.flow.request:
            self.master.view_flow(self.flow)
    elif key == "|":
        signals.status_prompt_path.send(
            prompt="Send flow to script",
            callback=self.master.run_script_once,
            args=(self.flow,),
        )
    elif key == "E":
        signals.status_prompt_onekey.send(
            self,
            prompt="Export to file",
            keys=[(e[0], e[1]) for e in export.EXPORTERS],
            callback=common.export_to_clip_or_file,
            args=(None, self.flow, common.ask_save_path),
        )
    elif key == "C":
        signals.status_prompt_onekey.send(
            self,
            prompt="Export to clipboard",
            keys=[(e[0], e[1]) for e in export.EXPORTERS],
            callback=common.export_to_clip_or_file,
            args=(None, self.flow, common.copy_to_clipboard_or_prompt),
        )
    elif key == "b":
        common.ask_save_body(None, self.flow)
    else:
        return key