Skip to content

fix(graphql): fall back to client-side vendor scoping when NetBox rejects template filters - #121

Merged
marcinpsk merged 1 commit into
mainfrom
fix/power-outlet-template-preload-fallback
Aug 21, 2026
Merged

fix(graphql): fall back to client-side vendor scoping when NetBox rejects template filters#121
marcinpsk merged 1 commit into
mainfrom
fix/power-outlet-template-preload-fallback

Conversation

@marcinpsk

@marcinpsk marcinpsk commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Fixes #120.

Root cause

NetBox 4.3.0 gave the GraphQL PowerOutletTemplateFilter the wrong mixin: ModularComponentModelFilterMixin (the one for device-attached components, exposing device/device_id/module/module_id) instead of ModularComponentTemplateFilterMixin (exposing device_type/module_type). Every other component template filter has the correct template mixin. As a result, the vendor-scoped preload query power_outlet_template_list(filters: {device_type: ...}) is rejected by the schema on every released 4.3.x and 4.4.x, with the exact error from the issue. Only the filter input type is broken; the unfiltered query and the device_type { id } / module_type { id } selections work.

NetBox fixed the mixin in netbox-community/netbox#20935, first shipped in v4.5.0. The 4.4.x line never received a backport (still broken in 4.4.10).

The importer only started tripping on this in v1.8.0, when the vendor-scoped GraphQL preload was introduced (#117). The weekly live integration lane tests against NetBox main, which has carried the fix since December 2025, so no CI lane ever exercised a released 4.3/4.4 schema.

Fix

get_component_templates catches GraphQLSchemaError on a vendor-scoped component query (schema rejection only; transport errors keep the existing retry and propagation behavior) and falls back to one unfiltered fetch of that endpoint, scoping the records client-side against the vendor's device type and module type ids. Ids are string-normalized on both sides of the comparison. If only the module leg is rejected while the device leg succeeded, the fallback keeps module-parented records alone and skips the device-type id fetch. This mirrors the existing image-attachment schema fallback and self-heals on NetBox >= 4.5.

Tests

Written red-first against the unfixed code, at the transport boundary (the client's real query construction and error classification run for real against a fake NetBox 4.4 responder):

  • both filter legs rejected: one unfiltered scan, correct vendor scoping across device- and module-parented records, foreign vendors excluded
  • module leg only rejected: no duplicates, no device-type id fetch, device leg untouched
  • transport failure: retries exhaust and propagate as a plain error, no fallback

Full suite: 1046 passed.

Summary by CodeRabbit

  • Bug Fixes

    • Improved vendor-scoped component template retrieval when server-side filtering is unavailable.
    • Matching device and module templates are now still returned through a compatible fallback.
    • Transport and connectivity errors continue to be reported normally.
  • Tests

    • Added coverage for filtering fallbacks, matching records, retry behavior, and error handling.

…ects template filters

NetBox 4.3.0 gave the GraphQL PowerOutletTemplateFilter the component
mixin (device/device_id) instead of the template mixin
(device_type/module_type), so vendor-scoped power_outlet_template_list
queries are rejected by the schema on every released 4.3.x and 4.4.x.
NetBox fixed the filter in netbox-community/netbox#20935, first shipped
in v4.5.0, with no backport to 4.4.x.

When a vendor-scoped component template query raises GraphQLSchemaError,
get_component_templates now fetches the endpoint unfiltered once and
scopes the records client-side against the vendor's device type and
module type ids (string-normalized on both sides). Transport errors keep
the existing retry and propagation behavior; only a schema rejection
triggers the fallback, so the slow path cannot hide a flaky server. An
asymmetric rejection (device leg accepted, module leg rejected) falls
back for the module leg alone without fetching device type ids.

Fixes #120
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 740fb4c4-0449-4ac7-8365-702ac4ef3971

📥 Commits

Reviewing files that changed from the base of the PR and between 88e7f6e and 551f786.

📒 Files selected for processing (2)
  • core/graphql_client.py
  • tests/test_graphql_client.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

get_component_templates now handles schema-rejected vendor filters with unfiltered scans and local parent-ID matching. Tests cover device and module fallbacks, pagination, scan selection, matching records, and transport-error propagation.

Changes

Vendor template fallback

Layer / File(s) Summary
Unfiltered vendor fallback implementation
core/graphql_client.py
The client adds a helper that fetches unfiltered templates and matches manufacturer device-type and module-type IDs. Schema errors trigger full or partial fallback scans. Transport errors still propagate.
Fallback and transport-error tests
tests/test_graphql_client.py
Tests cover paginated records, rejected filters, selective parent scans, matching results, and transport failures.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 551f7

The change adds a narrowly scoped fallback for rejected vendor filters while preserving transport-error behavior; no actionable merge-blocking risk remains after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant get_component_templates
  participant GraphQLEndpoint
  participant ManufacturerTypeQueries
  get_component_templates->>GraphQLEndpoint: Request vendor-filtered templates
  GraphQLEndpoint-->>get_component_templates: Return GraphQLSchemaError
  get_component_templates->>GraphQLEndpoint: Request unfiltered templates
  get_component_templates->>ManufacturerTypeQueries: Fetch manufacturer parent types
  ManufacturerTypeQueries-->>get_component_templates: Return parent IDs
  get_component_templates-->>get_component_templates: Filter templates by parent IDs
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 concisely describes the client-side fallback for vendor scoping when NetBox rejects GraphQL template filters.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

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.

@marcinpsk
marcinpsk merged commit 7eab324 into main Aug 21, 2026
11 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.

Field 'device_type' is not defined by type 'PowerOutletTemplateFilter'

1 participant