Skip to content

Bug: pcspec widget reverts to default after settings upload #1227

@js3110

Description

@js3110

Description

When uploading settings that include a specific pcspec (specimen) selection, the pcspec picker briefly shows the correct imported value but then reverts to the default (e.g., "PLASMA").

Root Cause

The bidirectional cascade between the analyte and pcspec observers in inst/shiny/modules/tab_nca/setup/settings.R causes a double-trigger that loses the imported pcspec value.

The sequence:

  1. settings_override() fires → pending_settings is set with imported settings
  2. Analyte observer fires → calls .consume_settings() (reads and clears pending_settings) → sets pcspec to the imported value via updatePickerInput → sets profile ✅
  3. Pcspec observer fires (triggered by step 2's updatePickerInput) → calls .consume_settings() → gets NULL (already consumed) → updates analyte picker with current value (no-op selection)
  4. Analyte observer fires again (triggered by step 3's updatePickerInput for analyte) → calls .consume_settings() → gets NULL → computes pcspec with no override → falls back to default_logic (grep for "plasma"/"serum") → overwrites the imported pcspec

The updating_filters guard doesn't prevent this because each observer resets the flag via on.exit() before the next observer fires (they run on separate flush cycles since updatePickerInput is async).

Expected Behavior

The pcspec picker should retain the imported value from settings after the cascade settles.

Possible Fix

The .consume_settings() pattern (read-once-then-clear) doesn't work with bidirectional cascades that span multiple flush cycles. Options:

  1. Don't clear pending_settings until the full cascade settles. Use a debounce or a counter to track how many cascade rounds have occurred, and only clear after the cascade is idle.
  2. Use a flag to skip the second analyte observer fire. After the analyte observer runs with settings, set a flag that prevents the next analyte observer fire from recomputing pcspec.
  3. Prevent the pcspec observer from re-triggering the analyte observer when the selection hasn't actually changed. Compare target_analyte with isolate(input$select_analyte) and skip the updatePickerInput call if they match.

Option 3 is the simplest and most targeted fix.

Steps to Reproduce

  1. Open the app and upload a dataset
  2. Configure NCA settings with a non-default pcspec (e.g., "URINE" instead of "PLASMA")
  3. Save settings to YAML
  4. Reload the app, upload the same dataset with the saved settings
  5. Observe that the pcspec picker shows the default value instead of the saved one

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status

In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions