Skip to content

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

Open
stktyagi wants to merge 7 commits intoopenwisp:masterfrom
stktyagi:master
Open

[fix] Merging with wrong format now raises Validation error #351#355
stktyagi wants to merge 7 commits intoopenwisp:masterfrom
stktyagi:master

Conversation

@stktyagi
Copy link
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
Copy link

coveralls commented Jun 12, 2025

Coverage Status

coverage: 99.182% (+0.002%) from 99.18%
when pulling aae7645 on stktyagi:master
into 39b85dc on openwisp:master.

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
Copy link

coderabbitai bot commented Feb 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c27d4d1f-8c20-4bed-b123-0ad62c28e166

📥 Commits

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

📒 Files selected for processing (1)
  • netjsonconfig/utils.py
📜 Recent review details
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: stktyagi
Repo: openwisp/netjsonconfig PR: 355
File: tests/openwrt/test_default.py:0-0
Timestamp: 2026-03-13T05:53:38.499Z
Learning: In netjsonconfig, when merging templates with incompatible types for the same key (e.g., a key is a dict in one template and a list in another), the `ValidationError` is raised at construction time (during the merge in `OpenWrt.__init__`), not during `validate()`. Custom config sections (e.g., `dhcp`) have no strict schema, so `validate()` would not catch type mismatches in those sections.
Learnt from: stktyagi
Repo: openwisp/netjsonconfig PR: 355
File: tests/openwrt/test_default.py:0-0
Timestamp: 2026-03-13T05:53:38.499Z
Learning: In the netjsonconfig codebase, `ValidationError` should be imported from `netjsonconfig.exceptions`, not from `jsonschema.exceptions`. This is the project convention used throughout the test suite (e.g., `tests/openwrt/test_default.py`).
📚 Learning: 2026-03-13T05:53:38.499Z
Learnt from: stktyagi
Repo: openwisp/netjsonconfig PR: 355
File: tests/openwrt/test_default.py:0-0
Timestamp: 2026-03-13T05:53:38.499Z
Learning: Enforce importing ValidationError from netjsonconfig.exceptions instead of jsonschema.exceptions across the codebase. This aligns with project conventions (including tests like tests/openwrt/test_default.py) and should be validated by CI. When reviewing Python files, flag any imports like from jsonschema.exceptions import ValidationError and suggest from netjsonconfig.exceptions import ValidationError (or equivalent relative import) to maintain consistency.

Applied to files:

  • netjsonconfig/utils.py
📚 Learning: 2026-03-13T05:53:38.499Z
Learnt from: stktyagi
Repo: openwisp/netjsonconfig PR: 355
File: tests/openwrt/test_default.py:0-0
Timestamp: 2026-03-13T05:53:38.499Z
Learning: In netjsonconfig, when merging templates with incompatible types for the same key (e.g., a key is a dict in one template and a list in another), the `ValidationError` is raised at construction time (during the merge in `OpenWrt.__init__`), not during `validate()`. Custom config sections (e.g., `dhcp`) have no strict schema, so `validate()` would not catch type mismatches in those sections.

Applied to files:

  • netjsonconfig/utils.py
🔇 Additional comments (3)
netjsonconfig/utils.py (3)

5-8: Import layering is correct and consistent.

Using local ValidationError with wrapped JsonSchemaError matches the project’s exception handling pattern cleanly.

Based on learnings: Enforce importing ValidationError from netjsonconfig.exceptions (or equivalent relative import) for project consistency.


26-26: Docstring contract update is accurate.

Good addition documenting the ValidationError raise path.


30-45: Container conflict guard is correctly scoped and fail-fast.

This logic now safely handles dict/list merge paths and raises a structured ValidationError for incompatible shapes, preventing uncaught merge failures.

Based on learnings: incompatible template-type conflicts are expected to raise ValidationError during merge/construction time.


📝 Walkthrough

Walkthrough

merge_config in netjsonconfig/utils.py was changed to only recurse when both existing and new values are dicts, using the existing value as the merge target. When both values are lists, merging is delegated to merge_list and list_identifiers is propagated. If the existing and new values are incompatible container types (dict vs list) or different primitive types, merge_config now raises a local ValidationError wrapping a JsonSchemaError with a descriptive message. The docstring was updated to document the raised ValidationError. tests/openwrt/test_default.py adds test_merge_invalid_format asserting a ValidationError for mixed-format templates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: merging configs with wrong format now raises a validation error instead of failing.
Description check ✅ Passed The PR description includes all required template sections and clearly describes the changes. The checklist is mostly complete, with only documentation updates marked incomplete.
Linked Issues check ✅ Passed The code changes fully address issue #351 by implementing type-mismatch checks in merge_config to raise ValidationError when incompatible container types are detected, preventing uncaught exceptions during validation.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing issue #351: error handling in merge_config logic and corresponding test coverage. No unrelated modifications are present.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link
Member

@nemesifier nemesifier left a comment

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
Copy link

@coderabbitai coderabbitai bot left a comment

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

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
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.

Copy link

@coderabbitai coderabbitai bot left a comment

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.

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
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