fix(enphase): delete schedules via POST /<id>/delete, not the DELETE verb - #4429
Merged
Conversation
…verb The schedule cleanup added in the previous commit used DELETE /battery/sites/<site>/schedules/<id>, which the BatteryConfig gateway rejects with "403 Invalid CORS request" - the verb is not allowed on that resource. The API exposes deletion as POST /schedules/<id>/delete, as the integration design notes already recorded. Every attempt failed, so a window Predbat wanted to retire was retried on each cycle and never cleared. A 403 also counts as an auth failure, so each one burned a re-login: six Enphase logins in fifteen minutes in the captured log, against an account that rejects excess sessions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes Enphase schedule cleanup by switching schedule deletion from the unsupported DELETE /.../schedules/<id> to the API-supported POST /.../schedules/<id>/delete, preventing persistent 403s and the resulting re-login churn in the Enphase BatteryConfig gateway path.
Changes:
- Update
EnphaseAPI._delete_schedule()to POST to the/deletesub-resource (withallow_empty=Trueto accept 204/no-body success). - Update and extend Enphase API tests to assert the correct delete endpoint/method and prevent regression.
- Bump Predbat version
v8.47.4→v8.47.5.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| apps/predbat/enphase.py | Switch schedule deletion to POST .../schedules/<id>/delete and document why (gateway rejects DELETE). |
| apps/predbat/tests/test_enphase_api.py | Add a focused regression test for the POST delete endpoint; update existing tests to match the new delete behavior. |
| apps/predbat/predbat.py | Version bump to v8.47.5. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #4428, which shipped the schedule-conflict fix but used the wrong delete endpoint.
Problem
The schedule cleanup in #4428 issued
DELETE /battery/sites/<site>/schedules/<id>. The BatteryConfig gateway does not allow that verb on the resource and rejects it:The API exposes deletion as
POST /schedules/<id>/delete— as the integration design notes indocs/superpowers/specs/2026-07-11-enphase-cloud-integration-design.mdalready recorded. The headers were never the problem:Origin/Refererare set for the battery_config family, and GET/PUT on the same base path succeed in the same session with the same headers. Only the verb differed.In a 15-minute deployed log: 28 delete attempts, all 403, zero successes.
Two consequences:
request_json, so each failed delete also burned a re-login — six Enphase logins in fifteen minutes, against an account that rejects excess sessions. (LOGIN_REUSE_SECONDS = 30bounded it, and no rejection or suspension was reached, but the churn is unnecessary.)What #4428 did fix
Same log, same site: zero
CONFLICTING_SCHEDULE_*errors, down from 272 in 13 hours. The id-pinning and conflict-retry changes are working; only the delete verb was wrong.Changes
_delete_schedulenow POSTs to the/deletesub-resource.test_delete_schedule_posts_to_the_delete_endpoint) that pins the endpoint so this cannot regress silently.Written test-first; the new test failed against the DELETE-verb implementation before the fix.
./run_pre_commitpasses — all hooks green, full quick suite green.Version bumped v8.47.4 → v8.47.5.
🤖 Generated with Claude Code