Troubleshooting¶
These are real failures we hit while building and deploying this app. Useful reading if you're adapting the pattern to another reticulate-based Shiny app.
- Troubleshooting
- App refuses to start: "Embeddings/config mismatch"
- App refuses to start: "Missing data/<parquet>"
- App fails to start: "Suitable Python installation for creating a venv not found"
- App boot loops: pyenv builds Python from source
- Boot succeeds but search fails: ModuleNotFoundError: No module named 'onnxruntime'
- .rscignore isn't honoring my patterns
- __pycache__/ leaks into the bundle
- App boots locally but fails on shinyapps.io with cannot open file 'renv/activate.R'
- Bundle preview shows the raw CSVs (101 MB) when they should be excluded
- "No shinyapps.io account configured"
- Multiple accounts: deploy uses the wrong one
- Quality drop after switching embedding models
- Local R can't find nanoparquet
- How to wipe state and rebuild
App refuses to start: "Embeddings/config mismatch"¶
Symptom (R console or server log):
Error: Embeddings/config mismatch: config.yml points to 'dd-abcd-7_0.parquet'
but embeddings were built for 'dd-abcd-6_0.parquet'. Run ./setup.sh to rebuild.
Cause: config.yml was bumped to a new dictionary release but ./setup.sh was not re-run, so the .npy/.npz artifacts on disk are still encoded against the previous parquet. app.R cross-checks config.yml against data/embeddings/manifest.txt at startup and refuses to launch on a mismatch — otherwise the UI would show the new version's title bar while the search returned rows from the old corpus.
Fix:
deploy.sh performs the same check before bundling, so the mismatch is caught before it ships.
App refuses to start: "Missing data/<parquet>"¶
Symptom:
Cause: config.yml's dictionary.parquet names a file that isn't in data/. Either the parquet was deleted, or config.yml was edited to point at a release that has not been produced yet.
Fix: Place the parquet at data/<that-filename> (see data/Readme.md), then run ./setup.sh.
App fails to start: "Suitable Python installation for creating a venv not found"¶
Symptom (server log):
Error in stop_no_virtualenv_starter(version = version, python = python) :
Suitable Python installation for creating a venv not found.
Requested Python: python3
Cause: shinyapps.io's modern Connect runtime ships no Python interpreter by default. The traditional virtualenv_create(python = "python3") pattern (from ~2019 examples) fails because nothing on PATH matches.
Fix: Don't try to call virtualenv_create() against a system python3. Use reticulate::py_require() instead — it triggers reticulate's uv-based auto-installer, which pulls a pre-built CPython tarball:
App boot loops: pyenv builds Python from source¶
Symptom:
…then silence for ~90 seconds, then the container restarts and tries again.
Cause: reticulate::install_python(version = "3.12.7") invokes pyenv install, which downloads the Python source tarball and compiles it. Even with optimized = FALSE, the build takes longer than shinyapps.io's app-startup window (~100 s).
Fix: Remove install_python() from app.R. The new py_require() path uses uv, which downloads a pre-built Python binary in ~2 s. See the previous section.
Boot succeeds but search fails: ModuleNotFoundError: No module named 'onnxruntime'¶
Symptom:
Downloading numpy (15.9MiB)
Downloaded numpy
Installed 1 package in 69ms
Error in py_run_file_impl(file, local, convert) :
ModuleNotFoundError: No module named 'onnxruntime'
Cause: Reticulate's auto-installer scans Python source for imports and tries to install only the packages it detects. Some import names don't match pip names (or aren't in reticulate's hardcoded mapping), so they get missed.
Fix: Declare dependencies explicitly before source_python():
py_require() adds every line of requirements.txt to the install list, regardless of what the scanner thinks.
.rscignore isn't honoring my patterns¶
Symptom: Files you listed in .rscignore still show up in the deploy bundle.
Cause: rsconnect:::ignoreBundleFiles() matches lines with exact-string setdiff() against the immediate contents of each directory — not gitignore-style globs:
ignored <- c("rsconnect", "renv", "packrat", ".git", ".gitignore", ".svn",
".Rhistory", ".Rproj.user", ".DS_Store", ".quarto", "app_cache",
"__pycache__/")
contents <- setdiff(contents, ignored)
Three implications:
- No trailing slashes.
sanity-chks/won't match the directory entrysanity-chks(no slash indir()output). - No nested paths.
data/dd-abcd-6_0.csvin a top-level.rscignoredoes nothing —datais the top-level entry,dd-abcd-6_0.csvis in the subdir. Add adata/.rscignore. - No globs.
*.csvwon't expand. Enumerate each file.
Fix: Use exact top-level names. For subdirectory exclusions, drop a .rscignore in that subdirectory. For things that genuinely need a glob (e.g. "every dd-abcd-*.parquet except the active one"), the filter lives in deploy.sh instead of .rscignore.
# .rscignore (top level)
sanity-chks
.claude
Dockerfile
setup.sh
run.sh
deploy.sh
shiny-chatbot-dictionary-abcd.Rproj
.RData
# data/.rscignore — exclude the source CSVs for the active release
dd-abcd-7_0.csv
dd-abcd-7_0_minimal.csv
dd-abcd-7_0_minimal_noimag.csv
__pycache__/ leaks into the bundle¶
Symptom: python/__pycache__/backend.cpython-312.pyc shows up in rsconnect::listDeploymentFiles() even though __pycache__/ is in rsconnect's own hardcoded exclude list.
Cause: The hardcoded entry is "__pycache__/" with a trailing slash, but dir() returns entries without slashes — setdiff() exact-match fails.
Fix: Delete python/__pycache__/ before listing/deploying. deploy.sh already does this:
App boots locally but fails on shinyapps.io with cannot open file 'renv/activate.R'¶
Cause: rsconnect excludes the entire renv/ directory from the deploy bundle (one of the hardcoded exclusions). If .Rprofile does an unguarded source("renv/activate.R"), the app crashes on first start.
Fix: Make the source() conditional in .Rprofile:
if (file.exists("renv/activate.R")) {
if (!requireNamespace("renv", quietly = TRUE)) install.packages("renv")
source("renv/activate.R")
}
shinyapps.io installs R packages from renv.lock independently, so the activation step isn't needed on the server.
Bundle preview shows the raw CSVs (101 MB) when they should be excluded¶
Cause: Most likely the .rscignore patterns are subpaths (data/dd-abcd-6_0.csv) in the top-level file, which don't match top-level entries. See the .rscignore section.
Fix: Move CSV exclusions into data/.rscignore. Verify with:
Rscript -e '
files <- rsconnect::listDeploymentFiles(".")
cat(length(files), "files,", sum(file.info(files)$size)/1e6, "MB\n")
'
Expected for the active 7.0 build: ~16 files, ~125 MB.
"No shinyapps.io account configured"¶
Cause: You haven't run rsconnect::setAccountInfo(...) yet, or you're running from a different user / R library where the credentials weren't stored.
Fix: Get a fresh token from shinyapps.io → Account → Tokens → Show and paste it into an R session. The credentials persist under ~/.config/rstudio/rsconnect/ (or ~/Library/Application Support/R/rsconnect/ on macOS).
Multiple accounts: deploy uses the wrong one¶
Cause: When more than one account is configured, deploy.sh errors out asking which to use.
Fix:
Quality drop after switching embedding models¶
If you swap MiniLM for something else, run sanity-chks/sanity_check_onnx.py (or write a variant) against your candidate model. Static-embedding models like model2vec fail badly on acronym-heavy queries (e.g. BMI) — we documented this in How it works.
Local R can't find nanoparquet¶
Cause: renv::restore() ran before nanoparquet was added to the lockfile.
Fix: setup.sh installs it automatically. To do it manually:
How to wipe state and rebuild¶
./clean_artifacts.sh # interactive — answer y to both prompts
rm -rf python_env # if clean script didn't remove it
./setup.sh
./run.sh
This is the right sequence after upgrading requirements.txt or changing python/build_embeddings.py.