Skip to content

Raise errors while computing cache digests - #2712

Merged
joelhawksley merged 9 commits into
ViewComponent:mainfrom
erikaxel:vc-digest-report-swallowed-errors
Sep 22, 2026
Merged

joelhawksley merged 9 commits into
ViewComponent:mainfrom
erikaxel:vc-digest-report-swallowed-errors

Conversation

@erikaxel

@erikaxel erikaxel commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The component digest machinery rescued every unexpected error and returned a neutral value:

  • CacheDigest::Resolver#find_templates returned []
  • CacheDigest.constantize_component returned nil
  • CacheDigest.partial_paths_in returned []
  • DependencyTracking#find_dependencies fell back to Rails' dependencies

A misconfiguration, failed autoload, raising component hook, parser failure, or filesystem error could therefore make a component untracked. Its fragment digest would stop changing and stale HTML could be served with no indication that digest computation had failed.

Rails does not rescue exceptions from dependency tracking or digest-tree construction. It only creates a missing digest node when template lookup normally returns no template.

Fix

Remove the broad rescues and let unexpected digest errors propagate, matching Rails' behavior. Expected missing constants continue to return nil through safe_constantize, and an ordinary unresolved template continues to use Rails' existing missing-node behavior.

Tests

Public .cache_digest integration tests use real cacheable components to verify that failures propagate through the complete digest stack:

  • A dependency referenced from a component's Ruby source raises while autoloading, exercising resolver synthesis and component constantization.
  • A dependency referenced from a component template raises while autoloading, exercising Rails dependency tracking and component constantization.
  • A real digest source cannot be read, exercising filesystem failure propagation through the resolver.

The tests do not stub ViewComponent internals or call private APIs.

Validated locally with:

  • bundle exec rake all_tests
  • the focused caching test suite
  • StandardRB on the touched Ruby files

The full suite completed with 637 Minitests, 5 engine compatibility tests, and 8 RSpec examples, with no failures.

@erikaxel
erikaxel force-pushed the vc-digest-report-swallowed-errors branch from 0c7ba27 to 3f3f1c3 Compare September 3, 2026 11:55
Every rescue in the digest machinery returns a neutral value, so a
misconfiguration, an autoload failure, or a raising `inherited` hook
degrades to "no component dependencies" and the application serves
stale HTML with nothing reported anywhere.

- Route the four swallow sites through CacheDigest.handle_error
- Log at `warn` through ActiveSupport's logger, preserving the production
  guarantee that a stale fragment beats a failed render
- Raise instead in local environments, configurable with
  config.view_component.raise_on_cache_digest_errors
joelhawksley and others added 2 commits September 22, 2026 13:27
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Match Rails' digest behavior by allowing parser, autoload, dependency tracker, and resolver failures to propagate instead of silently leaving components untracked.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@joelhawksley joelhawksley changed the title Report the errors swallowed while computing a cache digest Raise errors while computing cache digests Sep 22, 2026
joelhawksley and others added 5 commits September 22, 2026 13:53
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace CacheDigest stubs and private constantization calls with a cacheable component exercised through the public cache_digest API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use a real cache key method that raises during a normal cached render instead of overriding component internals.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Exercise autoload, template dependency tracking, and digest source failures through real components and cache_digest without stubbing ViewComponent internals.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use a dedicated Rails autoload path for failing dependency fixtures instead of inline Ruby autoload declarations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread docs/CHANGELOG.md Outdated
@joelhawksley
joelhawksley merged commit 0eb9e0e into ViewComponent:main Sep 22, 2026
19 checks passed
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.

2 participants