Skip to content

[change] Merging with wrong format now raises Validation error #351#355

Merged
nemesifier merged 11 commits into
openwisp:masterfrom
stktyagi:master
May 18, 2026
Merged

[change] Merging with wrong format now raises Validation error #351#355
nemesifier merged 11 commits into
openwisp:masterfrom
stktyagi:master

Conversation

@stktyagi

Copy link
Copy Markdown
Member

An attempt to merge config with wrong format will now raise a validation error instead of failing.

Fixes #351

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.

Reference to Existing Issue

Closes #351

Description of Changes

Added conditionals to check if two template types can be merged and if not raise validation error instead of failing.



An attempt to merge config with wrong format will now raise a validation error instead of failing.

Fixes openwisp#351
@coveralls

coveralls commented Jun 12, 2025

Copy link
Copy Markdown

Coverage Status

coverage: 99.143% (-0.04%) from 99.18% — stktyagi:master into openwisp:master

Comment thread netjsonconfig/utils.py Outdated
stktyagi and others added 3 commits October 26, 2025 15:19
It only prevents the original AttributeError crash and correctly lets the .validate() method handle all validation of the final merged configuration.

Fixes openwisp#351
@coderabbitai

coderabbitai Bot commented Feb 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

merge_config in netjsonconfig/utils.py now only recurses when both existing and new values are dicts; list merging occurs only when both sides are lists (via merge_list). If existing and new values are incompatible container types (dict vs list), merge_config raises a local ValidationError that wraps a jsonschema.ValidationError with an expected/got type message. netjsonconfig/exceptions.py adds guards in _list_errors and omits schema details in str when no errors exist. Tests were added to verify list-overridden-by-scalar behavior and that dict-vs-list merges raise ValidationError.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title uses [change] prefix but the PR description and objectives indicate this is a bug fix (labeled as 'bug', issue #351 is marked as a bug, and the fix addresses an uncaught exception). Update the title prefix from [change] to [fix] to accurately reflect that this PR fixes a bug where incompatible template formats cause uncaught exceptions, as stated in the PR objectives and commit message.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description covers all required sections from the template: checklist completion (with documentation noted as not updated), reference to issue #351, and a clear description of changes made.
Linked Issues check ✅ Passed The PR fully addresses issue #351 requirements: it raises a ValidationError when incompatible template formats (dict vs list) are merged, preventing uncaught exceptions during validation and providing proper error handling.
Out of Scope Changes check ✅ Passed All changes are directly scoped to addressing issue #351: merge validation, error handling for incompatible types, test coverage for new behavior, and defensive exception handling - no unrelated modifications present.
Bug Fixes ✅ Passed Bug fix properly addresses root cause with explicit ValidationError for incompatible dict-list merges. Comprehensive regression tests included and verified to be deterministic.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

@nemesifier nemesifier left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stktyagi the description says:

An attempt to merge config with wrong format will now raise a validation error instead of failing.

However, I don't see this in this implementation, nor in the test. No validation error is raised, it looks as if the error is silently ignored, which is not what I was expecting.

Why this inconsistency? Is this intentional?

@nemesifier nemesifier added the bug label Mar 12, 2026
@nemesifier nemesifier changed the title [Fix] Merging with wrong format now raises Validation error #351 [fix] Merging with wrong format now raises Validation error #351 Mar 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/openwrt/test_default.py`:
- Around line 249-272: The test test_merge_invalid_format currently calls
o.validate() without asserting failure; update it to expect a ValidationError by
wrapping the call in a pytest.raises(ValidationError) context (or using the test
framework's equivalent) and ensure ValidationError is imported from the module
that defines it; reference the OpenWrt class and its validate() call (i.e., wrap
OpenWrt(...).validate() in the raises block) so the test will fail if no
ValidationError is raised.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4f361efe-c095-4ed5-88cc-86211f95ba8a

📥 Commits

Reviewing files that changed from the base of the PR and between f007bd0 and ada4cbd.

📒 Files selected for processing (1)
  • tests/openwrt/test_default.py

Comment thread tests/openwrt/test_default.py Outdated
Merge_config now raises ValidationError when templates have incompatible types for the same key (e.g. list vs dict), instead of silently overwriting.
Test updated to assert ValidationError.

Fixes openwisp#351
@stktyagi

Copy link
Copy Markdown
Member Author

Why this inconsistency? Is this intentional?

@nemesifier, I must have missed this while updating all my PRs in feb. These changes don't make sense. I apologise for the oversight, I've added changes as per requirements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@netjsonconfig/utils.py`:
- Around line 30-40: The current check in merge_config rejects any differing
scalar types; change it so scalar overrides are allowed and only container-shape
conflicts raise. In the block handling key/value merges (referencing
merge_config, result, key, value and merge_list), replace the broad
type-mismatch check with logic that only raises a ValidationError when one side
is a container (dict or list) and the other is not the same container type
(e.g., dict vs list or dict vs scalar), allowing differing primitive scalars
(int vs str vs bool) to overwrite the template.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6f65b1a5-55aa-4fc8-b948-073e80837fd2

📥 Commits

Reviewing files that changed from the base of the PR and between ada4cbd and 9d0c8b1.

📒 Files selected for processing (2)
  • netjsonconfig/utils.py
  • tests/openwrt/test_default.py
📜 Review details
🔇 Additional comments (1)
tests/openwrt/test_default.py (1)

250-273: Good regression coverage.

This reproduces the dict-vs-list dhcp clash from the bug report and now asserts the expected ValidationError at merge time.

Comment thread netjsonconfig/utils.py Outdated
Narrowed the incompatible type check in merge_config to only
raise ValidationError when a dict or list conflicts with a
different type. Scalar overrides (e.g. str to int) are still
allowed as before.

Fixes openwisp#351
coderabbitai[bot]
coderabbitai Bot previously approved these changes Mar 13, 2026

@nemesifier nemesifier left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The direct reproduction from issue #351 now raises the project ValidationError, but I found two remaining problems that should be fixed before merge. See my comments below.

Comment thread netjsonconfig/utils.py
and type(value) is not type(existing)
):
raise ValidationError(
JsonSchemaError(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constructs a JsonSchemaError with only a message. That gives the right exception type, but netjsonconfig.exceptions.ValidationError.__str__ later assumes the wrapped jsonschema error has iterable validator_value and context. For this path, str(exc) raises TypeError: 'Unset' object is not iterable, so an uncaught error is shown as <exception str() failed> instead of the validation message. Please either make the wrapper tolerate message only errors, or build the wrapped error with the fields that __str__ expects. The test should also assert that the raised error can be stringified.

Comment thread netjsonconfig/utils.py
result[key] = merge_config(existing, value, list_identifiers)
elif isinstance(value, list) and isinstance(existing, list):
result[key] = merge_list(existing, value, list_identifiers)
elif (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard applies at every recursive merge level, not only to the top level package shape conflict from issue 351. It now rejects cases where a matched custom UCI block overrides a list option with a scalar option, even though the merge contract says simple values in the config overwrite values in the template. For example, a template dnsmasq block with server: ["1.1.1.1"] and device config with server: "8.8.8.8" used to merge, but now raises because existing is a list and value is a string. Please scope the validation to the package shape conflict or other cases that would otherwise crash, unless this broader behavior change is intentional and documented.

stktyagi and others added 2 commits May 16, 2026 22:44
Make NetJsonConfigException tolerant of message-only jsonschema errors to prevent TypeError during stringification. Scope type mismatch validation in merge_config strictly to complex shape conflicts (dict vs list).
@openwisp-companion

Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (1/3).

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 16, 2026
@openwisp-companion

Copy link
Copy Markdown

Proposed change log entry:

[fix] Raise ValidationError on incompatible merge types #351

When merging configuration templates, an incompatible type conflict between a dictionary and a list (or vice versa) will now raise a `ValidationError` instead of failing silently or with an uncaught exception. This ensures that configuration merging is more robust and predictable.

Closes #351

@nemesifier nemesifier changed the title [fix] Merging with wrong format now raises Validation error #351 [change] Merging with wrong format now raises Validation error #351 May 18, 2026
@kilo-code-bot

kilo-code-bot Bot commented May 18, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

The implementation correctly fixes issue #351 by adding type validation during config merging.

Highlights

Type safety: The new check properly detects incompatible types (dict vs list) and raises a clear ValidationError instead of causing an uncaught exception

Backward compatible: Scalar values can still override dicts/lists (existing behavior preserved) - only dict↔list mismatches are blocked

Error handling: Added null checks in _list_errors() prevent crashes when jsonschema errors lack context attributes

Well tested: Both unit tests (test_merge_config_incompatible_dict_list) and integration tests (test_merge_invalid_format) verify the fix

Clear error messages: The error indicates which key has the problem and shows expected vs received types

Files Reviewed (4 files)

  • netjsonconfig/utils.py - Type checking logic for merge_config()
  • netjsonconfig/exceptions.py - Null checks in _list_errors() and str()
  • tests/test_utils.py - Unit tests for the new validation
  • tests/openwrt/test_default.py - Integration test for OpenWrt backend

The fix is minimal, focused, and addresses the exact issue described. Good work! 🎉


Reviewed by kimi-k2.5 · 148,794 tokens

@nemesifier
nemesifier merged commit e6ccf8e into openwisp:master May 18, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Custom template with wrong format can cause uncaught exception

3 participants