# Buggy code
def _get_output_channel(
    request: Request, tracker: Optional[DialogueStateTracker]
) -> OutputChannel:
    """Returns the `OutputChannel` which should be used for the bot's responses.

    Args:
        request: HTTP request whose query parameters can specify which `OutputChannel`
                 should be used.
        tracker: Tracker for the conversation. Used to get the latest input channel.

    Returns:
        `OutputChannel` which should be used to return the bot's responses to.
    """
    requested_output_channel = request.args.get(OUTPUT_CHANNEL_QUERY_KEY)

    if (
        requested_output_channel == USE_LATEST_INPUT_CHANNEL_AS_OUTPUT_CHANNEL
        and tracker
    ):
        requested_output_channel = tracker.get_latest_input_channel()

    registered_input_channels = request.app.input_channels or []
    matching_channels = [
        channel
        for channel in registered_input_channels
        if channel.name() == requested_output_channel
    ]

    # Check if matching channels can provide a valid output channel,
    # otherwise use `CollectingOutputChannel`
    return reduce(
        lambda output_channel_created_so_far, input_channel: (
            input_channel.get_output_channel() or output_channel_created_so_far
        ),
        matching_channels,
        CollectingOutputChannel(),
    )


# Traceback (rasa.utils.endpoints.ClientResponseError)
PS D:\projects\chatbot\demo> docker run -it --rm -v ${pwd}:/app rasa/rasa interactive
Nothing changed. You can use the old model stored at '/app/models/20190730-083403.tar.gz'.
Bot loaded. Visualisation at http://localhost:5006/visualization.html.
Type a message and press enter (press 'Ctr-c' to exit).
Processed Story Blocks: 100%|████████████████████████████████████████████████████████████████████████████████████████| 4/4 [00:00<00:00, 1148.18it/s, # trackers=1]? Your input -> hi
? Your NLU model classified 'hi' with intent 'greet' and there are no entities, is this correct?  Yes

------
Chat History

#    Bot                        You
────────────────────────────────────────────
1    action_listen
────────────────────────────────────────────
2                                       hi
intent: greet 0.96
------
? The bot wants to run 'utter_greet', correct?  Yes
2019-07-30 08:34:53 ERROR    rasa.core.training.interactive  - failed to execute action!
2019-07-30 08:34:53 ERROR    rasa.core.training.interactive  - An exception occurred while recording messages.
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 1388, in record_messages
endpoint, sender_id, sender_ids, plot_file
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 906, in _predict_till_next_listen
action_name, policy, confidence, predictions, endpoint, sender_id
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 1075, in _validate_action
await send_action(endpoint, sender_id, action_name, policy, confidence)
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 195, in send_action
return await endpoint.request(json=payload, method="post", subpath=subpath)
File "/usr/local/lib/python3.6/site-packages/rasa/utils/endpoints.py", line 148, in request
resp.status, resp.reason, await resp.content.read()
rasa.utils.endpoints.ClientResponseError: 500, Internal Server Error, body='b'{"version":"1.1.8","status":"failure","message":"An unexpected error occurred. Error: \'Sanic\' object has no attribute \'input_channels\'","reason":"ConversationError","details":{},"help":null,"code":500}''
2019-07-30 08:34:53 ERROR    asyncio  - Task exception was never retrieved
future: <Task finished coro=<_serve_application.<locals>.run_interactive_io() done, defined at /usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py:1430> exception=ClientResponseError('500, Internal Server Error, body=\'b\'{"version":"1.1.8","status":"failure","message":"An unexpected error occurred. Error: \\\'Sanic\\\' object has no attribute \\\'input_channels\\\'","reason":"ConversationError","details":{},"help":null,"code":500}\'\'',)>
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 1437, in run_interactive_io
sender_id=uuid.uuid4().hex,
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 1388, in record_messages
endpoint, sender_id, sender_ids, plot_file
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 906, in _predict_till_next_listen
action_name, policy, confidence, predictions, endpoint, sender_id
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 1075, in _validate_action
await send_action(endpoint, sender_id, action_name, policy, confidence)
File "/usr/local/lib/python3.6/site-packages/rasa/core/training/interactive.py", line 195, in send_action
return await endpoint.request(json=payload, method="post", subpath=subpath)
File "/usr/local/lib/python3.6/site-packages/rasa/utils/endpoints.py", line 148, in request
resp.status, resp.reason, await resp.content.read()
rasa.utils.endpoints.ClientResponseError: 500, Internal Server Error, body='b'{"version":"1.1.8","status":"failure","message":"An unexpected error occurred. Error: \'Sanic\' object has no attribute \'input_channels\'","reason":"ConversationError","details":{},"help":null,"code":500}''

# Fixed code
def _get_output_channel(
    request: Request, tracker: Optional[DialogueStateTracker]
) -> OutputChannel:
    """Returns the `OutputChannel` which should be used for the bot's responses.

    Args:
        request: HTTP request whose query parameters can specify which `OutputChannel`
                 should be used.
        tracker: Tracker for the conversation. Used to get the latest input channel.

    Returns:
        `OutputChannel` which should be used to return the bot's responses to.
    """
    requested_output_channel = request.args.get(OUTPUT_CHANNEL_QUERY_KEY)

    if (
        requested_output_channel == USE_LATEST_INPUT_CHANNEL_AS_OUTPUT_CHANNEL
        and tracker
    ):
        requested_output_channel = tracker.get_latest_input_channel()

    # Interactive training does not set `input_channels`, hence we have to be cautious
    registered_input_channels = getattr(request.app, "input_channels", None) or []
    matching_channels = [
        channel
        for channel in registered_input_channels
        if channel.name() == requested_output_channel
    ]

    # Check if matching channels can provide a valid output channel,
    # otherwise use `CollectingOutputChannel`
    return reduce(
        lambda output_channel_created_so_far, input_channel: (
            input_channel.get_output_channel() or output_channel_created_so_far
        ),
        matching_channels,
        CollectingOutputChannel(),
    )