Update: The render-time validation behavior from this issue has been reverted in #3583333: Revert Render-Time Validation for Smooth Upgrade Path from 9.1.2 with Existing Invalid Content (merged via MR !187).
This issue remains for historical context. A later policy-driven redesign will reintroduce render-time validation in a more manageable way.
Problem/Motivation
Pattern content can be saved to the database without validation through several code paths, including:
- Direct entity manipulation via
PatternkitBlock::set('data', $value) - Form save operations that bypass validation
- Entity hooks that save blocks without validation checks
- Pattern update events with
$allowInvalid = TRUEflag - Bulk update operations (e.g., alt text population)
When invalid content is rendered, it can cause fatal errors or unexpected behavior during the rendering process. For example:
- Non-string values (numbers, objects, arrays) in string fields cause type errors
- Missing required fields cause validation failures
- Wrong data types cause rendering exceptions
This creates a poor user experience where pages can crash when invalid content is encountered, even if that content was saved through legitimate (but unvalidated) workflows.
Steps to reproduce
- Create a pattern block with valid content using the JSON editor form
- Save the block and find the block entity ID:
drush sqlq "SELECT id, info FROM patternkit_field_data ORDER BY id DESC LIMIT 5"Note the
idvalue for your block. - Update the block's data field directly in the database using Drush to contain invalid content:
Option A: Non-string value in string field (number instead of string)
drush sqlq "UPDATE patternkit_field_data SET data = '{\"text\": 123, \"formatted_text\": \"Valid text\"}' WHERE id = [BLOCK_ID]"Option B: Array value in string field
drush sqlq "UPDATE patternkit_field_data SET data = '{\"text\": [\"array\", \"values\"], \"formatted_text\": \"Valid text\"}' WHERE id = [BLOCK_ID]"Option C: Object value in string field
drush sqlq "UPDATE patternkit_field_data SET data = '{\"text\": {\"nested\": \"value\"}, \"formatted_text\": \"Valid text\"}' WHERE id = [BLOCK_ID]"Replace
[BLOCK_ID]with the actual block entity ID from step 2. - Clear Drupal cache:
drush cr - Attempt to view a page containing the block
- Expected: Page should display an error message for the invalid pattern
- Actual (before fix): Page may crash with fatal errors or exceptions
Proposed resolution
Add validation error handling in the pattern rendering pipeline to catch invalid content before it causes rendering failures. The implementation:
- Validates content during rendering in
Pattern::preRenderPatternElement()after config is set but before processing - Uses existing error handling infrastructure (
PatternRenderFailureEvent) for graceful error display - Displays error elements instead of crashing when invalid content is detected
- Works for all rendering paths (blocks, direct pattern elements, etc.)
Implementation details:
- Injected
PatternValidationHelperservice intoPatternelement via dependency injection - Added validation check that runs before
processSchemaValues() - On validation failure, dispatches
PatternRenderFailureEventwhich is handled by existingRenderFailureErrorDisplaySubscriber - Returns
PatternErrorelement with user-friendly error message instead of crashing
Error handling flow:
Invalid Content Detected ↓ Validation fails → Get exception → Dispatch PatternRenderFailureEvent ↓ Event handled? ├─ Yes → Return error element (pattern_error type) └─ No → Throw exception → Caught by outer catch → Default error message
Files modified:
src/Element/Pattern.php- Added validation helper injection and validation checktests/src/Unit/Element/PatternElementTest.php- Added validation test scenariostests/src/Kernel/Element/PatternInvalidContentTypeTest.php- Added kernel tests for invalid content types
Potential follow-up tasks
- Consider adding validation to entity save hooks as a preventive measure (separate from render-time validation)
- Monitor performance impact of validation during rendering
- Consider caching validation results if performance becomes an issue
- Document validation behavior in user-facing documentation
User interface changes
Error display:
- When invalid pattern content is encountered during rendering, users will see a user-friendly error message: "Failed to render pattern [pattern_name] ([pattern_id])"
- Error messages are displayed in place of the pattern content
- For users with "access devel information" permission, additional debug information is available in a collapsible details element
- No fatal errors or white screens of death occur
No breaking changes:
- Valid content continues to render normally
- Existing error handling for other failure types remains unchanged
- Form validation continues to work as before
API changes
New dependency injection:
Patternelement now requiresPatternValidationHelperservice in constructor- Service is injected via
Pattern::create()method usingpatternkit.helper.validationservice
No breaking changes:
- Existing code using
Patternelement will continue to work (service is auto-injected) - No changes to public API methods
- No changes to hook implementations
- No changes to event system (uses existing
PatternRenderFailureEvent)
Internal changes:
Pattern::preRenderPatternElement()now validates content before processing- Validation happens transparently - no API changes required for callers
Data model changes
No database schema changes:
- No new tables or fields added
- No changes to existing entity structures
- No migration required
Behavioral changes:
- Invalid content that was previously saved will now be caught during rendering
- Invalid content displays error messages instead of causing fatal errors
- This is a defensive measure - it doesn't prevent invalid data from being saved, but handles it gracefully when rendered
Issue fork patternkit-3563760
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
sluceroComment #6
sluceroI've uploaded a revised solution for this using a two-pass approach for validation to support the potential for pattern field processing to correct invalid content data. One example scenario would be having tokens saved in pattern content that would resolve to valid data items, but the token itself wouldn't validate.
Comment #7
sluceroTested and approved internally by @minsharm. Marking reviewed for merging.
Comment #9
sluceroMerged for inclusion in the 9.1.3 release.
Comment #12
sluceroUpdate: The render-time validation behavior from this issue has been reverted on
9.1.xin #3583333: Revert Render-Time Validation for Smooth Upgrade Path from 9.1.2 with Existing Invalid Content and merged via MR !187.The revert removed the two unconditional
assertValidPatternContent()calls fromPatternFieldProcessorPluginManager::processSchemaValuesbecause they caused upgrade regressions relative to 9.1.2 behavior:WARNINGlog noise on render for token-bearing values in format-constrained fields.The validation helper infrastructure was retained; only the unconditional render-path usage was reverted.
A later solution will reintroduce render-time validation with a more manageable, policy-driven design so upgrade behavior remains stable.