emilhe / dash-extensions

The dash-extensions package is a collection of utility functions, syntax extensions, and Dash components that aim to improve the Dash development experience

Home Page:https://www.dash-extensions.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

adding LogTransform to app causes Duplicate callback output error

matt-sd-watson opened this issue · comments

When adding the LogTransform as an app transformation:

transforms=[ServersideOutputTransform(backends=[backend_dir]),
                                    LogTransform()]

Upon opening, my app now has a Duplicate callback outputs error, despite not having the error without the transform.
The particular output in question uses a allow_duplicate=True flag as needed.

It is probably related to the recent change in callback structure when allow_duplicate=True flag was added. Could you post a small example demonstrating the issue?

I have the same issue. It came up as I upgraded my project dependencies from 0.1.13 to 1.0.4. It seems that there is an undocumented breaking change in 1.0.0? (I tried using 1.0.0 as a dependency instead of 1.0.4 but I still get the same error)

Interestingly, I just tried deploying my app with the LogTransform added using 0.1.13 and, while it works on my localhost, I do not see any logging messages on my deploy server.

I have tried replicating the issue with a small example but I am not able to replicate it on a small example. Here is the code I used in an attempt to replicate it:

import secrets
from dash_extensions.enrich import (
    DashProxy,
    LogTransform,
    Input,
    Output,
    State,
    DashLogger
)
from dash import dcc, html, no_update
import flask

server = flask.Flask(__name__)
app = DashProxy(
    transforms=[
        LogTransform(),
    ],
    external_stylesheets=[],
    server=server,
)

app.server.secret_key = secrets.token_urlsafe(16)

app.layout = html.Div([
    dcc.Input(id='text_input'),
    html.Button("Click me", id="input_button"),
    html.Button("Click me 2", id="input_button2"),
    html.H2(id="output_region")
])

@app.callback(
        Output("output_region", "children", allow_duplicate=True),
        State('text_input', 'value'),
        Input("input_button", "n_clicks"),
        prevent_initial_call=True,
        log=True,
    )
def callback1(
    input_text: str,
    button_clicks: int,
    dash_logger: DashLogger
    ):
    if not input_text:
        dash_logger.warning("Please input some text value before clicking")
        return no_update
    return input_text

@app.callback(
        Output("output_region", "children", allow_duplicate=True),
        State('text_input', 'value'),
        Input("input_button2", "n_clicks"),
        prevent_initial_call=True,
        log=True,
    )
def callback2(
    input_text: str,
    button_clicks: int,
    dash_logger: DashLogger
    ):
    if not input_text:
        dash_logger.warning("Please input some text value before clicking")
        return no_update
    return input_text

# Run App
if __name__ == "__main__":
    app.run(debug=True)

The app that I am running is a fairly large multi-page application. The outputs that triggered the error were not, in fact, duplicate outputs. Still, I added the allow_duplicate=True argument but it has no effect.

The other thing that I found interesting about the callbacks that triggered the error is that they are on two of my sub-pages which are fairly deep into the application. I thought that the error would have been triggered by one of my earlier callbacks.

EDIT:

I "fixed" the issue by just removing the logging behaviour from the offending callbacks. For me, it was on two non-critical functions. To confirm, though, the duplicate callbacks were on the dash mantine components notifications, not any of my Output objects. I used the default dmc notifications on the included DashLogger. So, for some reason, the notification outputs on those two callback functions seemed to be creating duplicate IDs on the notification component...that is, I am assuming that how the LoggingTransform works is by adding additional Output objects to the function. Since, I do not have access to those Output objects, it seems that I am not able to add the allow_duplicate=True on the Output objects that are actually causing the error.

Should be fixed in the 1.0.12 release. Please comment/re-open if you still see any issues.

The issue still appears to occur, I will try to develop another MRE to indicate

@emilhe, I might be mistaken but I think adding allow_duplicate=True to Outputs in 1.0.12 didn’t help for reasons well described in this issue: plotly/dash#2486

In my particular situation, I have two callbacks that share the same Inputs but had different Outputs, which works fine. However, after adding log=True to those callbacks, they now share the notification_provider Output with the same uid, which now does cause the “Duplicate callback outputs” issue.

I've been trying to make the log_id unique inside setup_notifications_log_config() and wasn't successful yet, but maybe that's a step in right direction?