Debug

Published

2025-03-13

Caution

The contents in this section are still being reviewed. Thank you for your patience.

Expand the callout boxes below to review what we’ve covered in the last section:

Data covered three common locations for storing and documenting data in R packages:

Launch describes the differences between Shiny run functions and what to include in the app.R file and standalone app function:

Resources covered how to include external files and/or resources in your app (i.e., those previously stored in www/):

This section covers common methods for debugging R code and how we can adapt these methods to use within a Shiny app. So far this book has covered the contents of an R package when it contains a basic, functional Shiny application. Consider the diagram below that illustrates the reactive inputs in our application:

%%{init: {'theme': 'neutral', 'themeVariables': { 'fontFamily': 'monospace', "fontSize":"13px"}}}%%
flowchart TD
    subgraph Inputs["<strong>Inputs</strong>"]
        subgraph Variables["Variables"]
        var_input[/"<code>input$x</code><br><code>input$y</code><br><code>input$z</code>"/]
        end
        subgraph Aesthetics["Aesthetics"]
        aes_input[/"<code>input$alpha</code><br><code>input$size</code>"/]
        end
        subgraph Title["Title"]
        plot_title[/"<code>input$plot_title</code>"/]
        end
        
    end
    subgraph React["<strong>App Reactives</strong>"]
        var_inputs>"<code>var_inputs()</code> "]
        inputs>"<code>inputs()</code>"]
    end
    subgraph Output["<strong>Output</strong>"]
        output[\"<code>output$scatterplot</code>"\]
    end

    var_input & aes_input <==> |"pre-selected values"|var_inputs 
    plot_title <-.-> |"empty string"|var_inputs 
    var_inputs <==> inputs
    inputs <==> output
    
    style var_input stroke:#333,stroke-width:1px,rx:5,ry:5 
    style aes_input stroke:#333,stroke-width:1px,rx:5,ry:5

Reactive flow in Movies App

The inputs are collected by the variable input module1 and passed to the graph display module (as var_inputs()),2 where they become the reactive inputs() for the graph utility function,3 before finally being rendered.

As applications grow in complexity, it’s highly likely you’ll encounter bugs or errors during development. Fortunately, both RStudio and Positron come with powerful interactive debuggers, which help us identify, analyze, and fix errors in our code.4

Our application launches with pre-selected values for the x, y and color graph inputs, along with values for the size and opacity (alpha) of the points. Users can add a title or change the graph inputs, but by having pre-selected values, we guarantee the graph renders when the application launches.

%%{init: {'theme': 'neutral', 'themeVariables': { 'fontFamily': 'monospace', "fontSize":"13px"}}}%%
flowchart TD
    subgraph Inputs["<strong>Inputs</strong>"]
        subgraph Variables["Variables"]
        var_input[/"<code>input$x</code><br><code>input$y</code><br><code>input$z</code>"/]
        end
        subgraph Aesthetics["Aesthetics"]
        aes_input[/"<code>input$alpha</code><br><code>input$size</code>"/]
        end
        subgraph Title["Title"]
        plot_title[/"<code>input$plot_title</code>"/]
        end
        
    end
    subgraph React["<strong>App Reactives</strong>"]
        var_inputs>"<code>var_inputs()</code> "]
        inputs>"<code>inputs()</code>"]
    end
    subgraph Output["<strong>Output</strong>"]
        output[\"<code>output$scatterplot</code>"\]
    end

    var_input & aes_input <==> |"pre-selected values"|var_inputs 
    plot_title <-.-> |"*new plot title*"|var_inputs 
    var_inputs <==>|"*New Plot Title*"|inputs
    inputs <==> output
    
    style var_input stroke:#333,stroke-width:1px,rx:5,ry:5 
    style aes_input stroke:#333,stroke-width:1px,rx:5,ry:5

Updating the plot title

Any text entered for the title is converted to title case when the variable inputs are passed to the scatter plot display module. The reactives in the application are all updated with the new output:

The new title is passed with var_inputs() to inputs() and updates the graph to display the text.

The new title is passed with var_inputs() to inputs() and updates the graph to display the text.

Shiny bugs

In Shiny apps, debugging can be challenging because the reactive model involves dynamic interactions and a non-linear flow of execution between inputs, reactive expressions, and outputs. Shiny is inherently asynchronous, so bugs can originate from reactive dependencies, execution order, utility functions, hidden states, lazy evaluation, and invalidation (i.e., reactive(), observe(), isolate(), etc.).

For example, we could have an incorrectly defined inputIds or outputIds in the UI, which causes our graph utility function to fail. We could also have missing parentheses on reactive values in the server. Finally, the bug could be originating from the output/render point.

%%{init: {'theme': 'neutral', 'themeVariables': { 'fontFamily': 'monospace', "fontSize":"16px"}}}%%
flowchart TD
    subgraph Inputs["<strong>Inputs</strong>"]
        subgraph Variables["Variables"]
        var_input[/"<code>input$x</code><br><code>input$y</code><br><code>input$z</code>"/]
        end
        subgraph Aesthetics["Aesthetics"]
        aes_input[/"<code>input$alpha</code><br><code>input$size</code>"/]
        end
        subgraph Title["Title"]
        plot_title[/"<code>input$plot_title</code>"/]
        end
    end
    IDs("<code>inputId</code> or <code>outputId</code> errors") --x var_input & aes_input & plot_title
    subgraph React["<strong>App Reactives</strong>"]
        var_inputs>"<code>var_inputs()</code> "]
        inputs>"<code>inputs()</code>"]
    end
    Obs("<code>observe</code> listener<br>errors") --x React
    Rxt("Reactive context<br>errors") --x Inputs & React
    subgraph Output["<strong>Output</strong>"]
        output[\"<code>output$scatterplot</code>"\]
    end
    Rend("<code>render_*</code> function<br>errors") ----x Output

    var_input & aes_input <==> var_inputs 
    plot_title <-.-> var_inputs 
    var_inputs <==> inputs
    inputs <==> output
    
    style var_input stroke:#333,stroke-width:1px,rx:5,ry:5 
    style aes_input stroke:#333,stroke-width:1px,rx:5,ry:5
    style IDs stroke:#333,stroke-width:1px,rx:10,ry:10
    style Obs stroke:#333,stroke-width:1px,rx:10,ry:10
    style Rend stroke:#333,stroke-width:1px,rx:10,ry:10
    style Rxt stroke:#333,stroke-width:1px,rx:10,ry:10

Possible locations of bugs in a reactive model

Understanding the interplay of reactivity, lazy evaluation, and asynchronous execution will help us diagnose and resolve bugs in our Shiny app. We have to employ specific strategies and tools to handle Shiny bugs effectively, and some of the traditional debugging approaches can fall short in reactive contexts.

Debuggers

10  Debuggers covers the interactive debugger in the Positron IDE.

Debugging apps

12  Debugging apps dives deeper into debugging modules and the server logic in our app-package.

Logging

13  Logging covers using logging to keep track of application and session behaviors.


  1. Our variable input model is in R/mod_var_input.R.↩︎

  2. The graph display module is in R/mod_scatter_display.R.↩︎

  3. The graph utility function is in R/scatter_plot.R↩︎

  4. The definition in this article from AWS gives a great general overview of debugging.↩︎