Skip to content

fix(accounts): skip digest on sidebar fragment cache#2776

Open
pro3958 wants to merge 1 commit into
we-promise:mainfrom
pro3958:fix/issue-2516
Open

fix(accounts): skip digest on sidebar fragment cache#2776
pro3958 wants to merge 1 commit into
we-promise:mainfrom
pro3958:fix/issue-2516

Conversation

@pro3958

@pro3958 pro3958 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #2516.

Self-hosted deployments repeatedly logged a bogus Rails cache-digest error when
rendering the account sidebar:

ERROR -- :   Couldn't find template for digesting: Ds/D

The line looks like an application failure, but the page renders correctly — it
is pure log noise, and because it fires on every sidebar cache miss it can bury
real errors in production logs.

Root cause

app/views/accounts/_account_sidebar_tabs.html.erb wraps the sidebar in a
fragment cache and renders several DS::* view components inside the cache
block (render DS::Alert.new(...), render DS::Tabs.new(...), etc.).

Rails' ERB dependency tracker parses render DS::… as a dynamic render
dependency named DS, then singularizes/inflects it into the nonexistent
partial name Ds/D. When the cache helper computes the template digest,
ActionView::Digestor tries to resolve that partial, fails, and logs
Couldn't find template for digesting: Ds/D.

Fix

The fragment's cache key is already manually versioned and invalidated:

family.build_cache_key("account_sidebar_tabs_v2", invalidate_on_data_updates: true)

Since automatic template digesting adds nothing here (the key already includes
every runtime dimension), the cache block opts out of it with skip_digest: true. With digesting skipped, ActionView::Digestor is never invoked for this
fragment, so the spurious Ds/D lookup — and its error log — no longer happen.
Rendered output is unchanged.

A comment on the template documents the opt-out and notes that the
account_sidebar_tabs_v2 version suffix must be bumped manually when the
template or its sidebar dependencies change, since the digest no longer tracks
that automatically.

Tests

Added a regression test in test/controllers/accounts_controller_test.rb that
renders the accounts page with fragment caching enabled and asserts the log
contains no Couldn't find template for digesting line. It fails before the fix
(the digestor logs the Ds/D error) and passes after it.

Notes

  • No UI/visual change — the sidebar renders identically; this only removes a
    log-side-effect during digest computation.
  • No migration.
Notes I made while reviewing this
  • minor app/views/accounts/_account_sidebar_tabs.html.erb:11 — Opting out of template digesting means edits to this template, the nested accounts/accountable_group partial, or the DS::* components will no longer bust the fragment cache automatically; on self-hosted deploys a stale sidebar can persist up to 12h unless someone bumps the _v2 suffix. This is inherent to skip_digest, not a bug, and the comment already flags the requirement — noting it so the human reviewer is aware the deploy-time invalidation contract now depends on discipline.
  • minor app/views/accounts/_account_sidebar_tabs.html.erb:11 — skip_digest: true also remains in the options hash passed through to the cache store's write_fragment, alongside expires_in. This is harmless (stores ignore unknown options) and is the idiomatic Rails call form, so no change is needed.
  • minor app/views/accounts/_account_sidebar_tabs.html.erb:11 — skip_digest removes template-source from the cache key, so future edits to this partial (or its rendered DS::* components) no longer auto-invalidate the 12h fragment cache — stale UI can be served until the version suffix is bumped manually. This is intentional and documented, but it shifts an invalidation guarantee onto developer discipline.
  • minor test/controllers/accounts_controller_test.rb:433 — The regression test relies on the fragment's template digest being computed fresh within this test. ActionView memoizes digests process-wide, so if any other test ever enabled perform_caching for a page that renders this partial, the digest (and its error) would be logged elsewhere and this assert_no_match would pass even on unfixed code. Currently no other test enables caching, so it should genuinely fail without the fix — but the isolation is implicit, not guaranteed.
  • minor app/views/accounts/_account_sidebar_tabs.html.erb:8 — skip_digest disables automatic cache invalidation on template edits, so future changes to this partial (or its sidebar dependencies) will serve stale fragments until the version suffix is bumped. This is a real behavioral tradeoff, though it matches the fragment's existing manual-versioning design.
  • minor test/controllers/accounts_controller_test.rb:433 — Gates could not be executed in this review environment (no Ruby/bundler), so bin/rails test / rubocop / erb_lint green status is asserted by inspection only.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed account sidebar caching to prevent misleading template digest errors from appearing in logs.
    • Corrected SimpleFin account setup and relinking call-to-action visibility across different account states.
  • Tests

    • Added regression coverage for sidebar cache logging and SimpleFin call-to-action behavior.

@pro3958

pro3958 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Correct, minimal fix: skip_digest: true bypasses ActionView's digestor for this fragment, which is the right call since the key is already manually versioned (account_sidebar_tabs_v2 + invalidate_on_data_updates: true) — this removes the mis-parsed Ds/D dependency and its error log rather than papering over it. The regression test is real: it's the only test that enables perform_caching, so the sidebar digest is computed for the first time inside the test with the captured logger, and it would log the error on unfixed code. Only caveat worth knowing: with digesting off, template/DS-component changes won't auto-invalidate this cache, so the documented _v2 bump must be honored on future edits.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@pro3958, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 46 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1cfb08e3-38aa-4303-9c41-3c6a75448abd

📥 Commits

Reviewing files that changed from the base of the PR and between 6e20333 and 9f16529.

📒 Files selected for processing (2)
  • app/views/accounts/_account_sidebar_tabs.html.erb
  • test/controllers/accounts_controller_test.rb
📝 Walkthrough

Walkthrough

The sidebar fragment cache now skips Rails template digesting, with a regression test for bogus digest logs. Additional integration tests cover SimpleFin CTA rendering across linked, unlinked, manual-account, and no-account scenarios.

Changes

Sidebar cache digest handling

Layer / File(s) Summary
Disable sidebar cache digesting
app/views/accounts/_account_sidebar_tabs.html.erb, test/controllers/accounts_controller_test.rb
The sidebar cache uses skip_digest: true with manually versioned invalidation, and a regression test verifies that rendering does not log the bogus template digest error.

SimpleFin CTA coverage

Layer / File(s) Summary
Cover SimpleFin CTA states
test/controllers/accounts_controller_test.rb
Integration tests verify setup and relink CTA visibility for unlinked SimpleFin accounts, manual accounts, and accounts without SimpleFin data.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: performance

Suggested reviewers: jjmata

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The added SimpleFin CTA integration tests are unrelated to #2516 and the digest-log fix. Move the SimpleFin CTA tests to a separate PR unless they are required for this issue's acceptance criteria.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: disabling digesting for the account sidebar fragment cache.
Linked Issues check ✅ Passed The fix and regression test address #2516 by suppressing the bogus Ds/D digest log without changing sidebar rendering.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pro3958
pro3958 marked this pull request as ready for review July 23, 2026 17:21
The account sidebar fragment renders DS::* view components. Rails' ERB
dependency tracker parses `render DS::Foo.new` as a dynamic render
dependency named DS and inflects it into the nonexistent partial "Ds/D".
When the cache helper computes the template digest, ActionView::Digestor
fails to resolve that partial and logs "Couldn't find template for
digesting: Ds/D" on every sidebar cache miss.

The fragment's cache key is already manually versioned and invalidated
via account_sidebar_tabs_cache_key ("account_sidebar_tabs_v2",
invalidate_on_data_updates: true), so automatic template digesting adds
nothing. Pass skip_digest: true to the cache block so the digestor never
runs for this fragment. Rendered output is unchanged.

Fixes we-promise#2516

jjmata commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Review

What it does: Adds skip_digest: true to the cache block in _account_sidebar_tabs.html.erb to stop ActionView::Digestor from mis-parsing render DS::Alert.new(...) / DS::Tabs.new(...) calls as a bogus Ds/D partial dependency, which was logging Couldn't find template for digesting: Ds/D on every cache miss.

Correctness: skip_digest: is a legitimate, documented option on the cache view helper — this is the right fix rather than a workaround. I verified account_sidebar_tabs_cache_key (app/helpers/accounts_helper.rb:29) already composes the key from family.build_cache_key(...), Current.user.id, share count/max-updated-at, active_tab, mobile, locale, and active account id — so dropping the template digest doesn't introduce any cross-family/cross-user staleness; the digest was never a security-relevant part of the key, just a change-detection hash. This is also the only cache block in the app rendering DS::* inside it (grep "<% cache " app/views), so the fix is complete for the known bug pattern.

Test coverage: The new test in test/controllers/accounts_controller_test.rb:433 genuinely exercises the buggy path — test env uses :null_store (always a cache miss) and ActionView::Digestor memoizes per-process, and this is the only test enabling perform_caching, so it should fail pre-fix and pass post-fix as claimed.

Minor, non-blocking: the tradeoff already called out in the code comment (losing auto-invalidation on template edits, relying on the _v2/_v3 bump) is real but acceptable given the existing manual-versioning design. No i18n/convention issues — no user-facing strings or business logic touched.

Looks good to merge.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rails cache digest logs bogus Ds/D dependency for account sidebar

2 participants