Skip to content

Fix data fetch breaking on jsonpath namespace collision (TypeError: 'module' object is not callable) - #322

Closed
jelmerkk wants to merge 1 commit into
vincentwolsink:mainfrom
jelmerkk:fix-jsonpath-namespace-collision
Closed

Fix data fetch breaking on jsonpath namespace collision (TypeError: 'module' object is not callable)#322
jelmerkk wants to merge 1 commit into
vincentwolsink:mainfrom
jelmerkk:fix-jsonpath-namespace-collision

Conversation

@jelmerkk

@jelmerkk jelmerkk commented Jun 26, 2026

Copy link
Copy Markdown

Problem

On 2026.7b1 the integration stops fetching and all entities go unavailable, with the coordinator logging:

ERROR (MainThread) [custom_components.enphase_envoy] Unexpected error fetching envoy ... data
  File ".../envoy_reader.py", line 410, in _resolve_path
    result = jsonpath(self.data, path)
TypeError: 'module' object is not callable

Root cause

manifest.json requires the jsonpath PyPI package, and envoy_reader.py does from jsonpath import jsonpath expecting a callable. That import name is shared with jsonpath-python, which recent HA cores pull in transitively. When jsonpath-python wins the shared environment, from jsonpath import jsonpath resolves to a submodule instead of the function, so every jsonpath(...) call raises TypeError: 'module' object is not callable. It fails in detect_model() (endpoint_info.envoy_info.device.imeter), which runs for every model, so it affects metered and non-metered units alike.

Fix

Drop the external jsonpath dependency and vendor a tiny resolver. The integration only ever calls jsonpath() with simple dotted key/index paths (e.g. channels[0].watts.now, endpoint_info.envoy_info.device.imeter) — no wildcards, filters or recursion — so a ~15-line resolver fully preserves behaviour (single-element list on match, False otherwise) while removing the dependency, and the namespace collision, entirely.

  • envoy_reader.py: remove from jsonpath import jsonpath, add vendored jsonpath() (both call sites unchanged).
  • manifest.json: drop jsonpath from requirements.

Testing

Applied to a live non-metered (Standard) Envoy on HA 2026.7 beta: the TypeError is gone, the coordinator fetches cleanly, and sensor.envoy_current_power_production resumed reporting. python -m py_compile passes.

🤖 Generated with help from Claude Code

The `jsonpath` PyPI package shares its top-level import name with
`jsonpath-python`, which recent Home Assistant cores pull in transitively.
When that package wins in the shared environment, `from jsonpath import
jsonpath` resolves to a submodule instead of the callable, so every
`jsonpath(...)` call raises `TypeError: 'module' object is not callable` in
`_resolve_path` / `detect_model` and the coordinator fails with
"Unexpected error fetching envoy ... data" — all entities go unavailable.
Seen on HA 2026.7 beta.

Drop the external `jsonpath` dependency and vendor a tiny resolver for the
simple dotted key/index paths this integration actually uses (e.g.
`channels[0].watts.now`). No wildcards, filters or recursion are used, so the
behaviour is preserved (single-element list on match, False otherwise) while
removing the dependency and the collision entirely.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@HenkSnavel

Copy link
Copy Markdown

Heads-up: this fixes the import-name collision, but the dotted-path parser here
doesn't evaluate the [?(...)] filter expressions the integration relies on, so
most sensors stay empty. For example:

production[?(@.type=='inverters' && @.activeCount > 0)].wNow   -> None
consumption[?(@.measurementType == 'net-consumption')].wNow    -> None

Only the simple non-filter paths populate. I hit exactly this on HA core 2026.7
(Python 3.14) and opened #324 as an alternative: it vendors the full Goessner
jsonpath 0.82 engine in-tree (MIT), so the [?(...)] filter + flattening
semantics are preserved and all existing path strings work unchanged — verified
1:1 against the original package and on a live 3-phase Envoy (44 sensors).

Either way the requirement should be dropped from manifest.json; just flagging
so the filter paths don't silently regress. 🙂

@vincentwolsink

Copy link
Copy Markdown
Owner

#326

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.

3 participants