Repository navigation
Description
Summary
On a Wi-Fi 7 router whose 2.4 GHz and 5 GHz radios share one wiphy, a WLAN on both bands is rendered into the same UCI section. Only one band comes up on the router, and the Apply stops with an ownership-recording error.
Environment
- oonfeeWRT v0.1.5 (container); code path unchanged in v0.1.7, see below
- Tenda BE12 Pro,
mediatek/filogic, OpenWrt SNAPSHOT r35063-7edb29d241 - Device mode: Managed
Steps to reproduce
- Adopt the BE12 Pro as a managed device.
- Create a WLAN on 2.4 GHz and 5 GHz.
- Preview → Apply.
Actual result
The Apply stops after this device:
Stopped after <device>: device outcome was applied, but controller ownership recording failed:
reconcile: applied but could not record ownership: store: record ownership claim: constraint failed:
UNIQUE constraint failed: owned_sections.device_id, owned_sections.config, owned_sections.section (1555)
On the router only one of the two bands was up afterwards.
Expected result
One wifi-iface per UCI radio (oowrt_wlanN_radio0 on radio0, oowrt_wlanN_radio1 on radio1), both bands up, Apply completes.
Cause
radioSection() in internal/render/render.go derives the UCI wifi-device from the phy index (phy0 → radio0). On this board both radios are served by one wiphy:
$ iw dev
phy#0
Interface phy0.1-ap0
channel 52 (5260 MHz), width: 80 MHz
Interface phy0.0-ap0
channel 1 (2412 MHz), width: 20 MHz
radio0 band=2g radio=0 path=soc/11280000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0
radio1 band=5g radio=1 path=soc/11280000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0
Both interfaces report phy0, so both bands map to radio0 and render a section with the same name. The router ends up with one of them, and recording ownership of the second fails on the unique index.
Suggested fix
luci-rpc.getWirelessDevices, which the capability probe already reads, is keyed by the UCI radio section. Keeping that key on capability.Radio (for example as Section) and preferring it in radioSection() fixes this, with the phy derivation kept as a fallback for capability records stored before the field existed. An already adopted device then needs one re-probe.
I have this change with tests (a render test for a two-radio wiphy, a probe test that each radio keeps its UCI section). It applies cleanly on current main (v0.1.7) and go test ./... passes there. With the patched build, re-probe and Apply on the BE12 Pro work and both bands are up. I'm happy to open a PR if that's useful to you, or you can take the idea as it is.
How this report was made
I use AI tooling and want to be clear about who did what:
- Me: running oonfeeWRT with three OpenWrt APs at home, hitting the failure in the UI, reviewing the patch, deploying the patched build, re-probing and applying, and confirming on the real BE12 Pro that both bands come up and Apply completes.
- Claude Code (Anthropic): tracing the error to
radioSection(), reading the router output above, writing the patch and tests, rebasing ontomainand running the test suite, and drafting this issue. - Not verified: v0.1.7 on hardware. The build I run is v0.1.5 plus this fix; for v0.1.7 I checked that
radioSection()is unchanged and that the patch applies cleanly with passing tests.
Activity
aiden0rchad commentedon Sep 17, 2026
Great job filing this report, I dont mind that your agent filed this report for you, It gave a very detail report. I'm currently testing solutions at the moment, I dont exactly have the same hardware but if you wouldnt mind testing out a build and verifying if works. If it does, do let me know and I will be pushing it to main asap
aiden0rchad commentedon Sep 17, 2026
Following up with the proposed fix: #42 (commit
b3b7adfec9549c901c72601f49bada8a1e96ec5e). Thanks @flubba for the detailed diagnosis and the UCI-section approach.The patch retains each configured radio's UCI section even when both use
phy0. It also rejects ambiguous saved radio mappings and duplicate desired sections before router writes or ownership recording. It does not work around the error by weakening the database constraint.The full capability, rendering, and reconciliation test suites, vet, and documentation build passed locally. Tests cover a two-band/shared-PHY probe, both distinct rendered targets, an idempotent next plan after a mock-backed Apply, and rejection of duplicates before side effects. Independent review is complete; GitHub's full CI is running on the PR.
Could you verify this exact PR build on the BE12 Pro? Your existing hardware verification was on your own v0.1.5 patch; I have not tested this build on that hardware. The local wired lab connection is currently unavailable.
Before testing, preserve your pre-upgrade recovery backup: this PR is based on v0.1.7, so upgrading from v0.1.5 still requires the normal upgrade precautions. Then Re-probe capabilities → Preview and check that the two bands have distinct UCI sections/device references. Only Apply if the preview is correct and it is safe to change the router. Please confirm both bands work and a subsequent Preview is clean.
A previous failed Apply may already have changed the router; please don't reset the database, clear ownership records, or re-adopt as a workaround. If this build still fails, share sanitized re-probe/preview evidence and the exact error, without credentials or wireless keys. Leaving the issue open until you can verify.
flubba commentedon Sep 17, 2026
Verified on the BE12 Pro. The PR build behaves correctly here.
Build provenance
codex/issue-39-shared-wiphyatb3b7adfec9549c901c72601f49bada8a1e96ec5e, no local modifications.deploy/Dockerfile, taggedv0.1.7-pr42-b3b7adf. Compose and environment unchanged from my previous deployment; only the image tag changed.Upgrade precautions
data/(database +keyring.json) and the runtime passphrase copied aside. Copy verified: identical SHA-256 for database, keyring and passphrase,PRAGMA integrity_check= ok, empty WAL,schema_version= 23. The v0.1.5 image is retained./healthz= 200, no warnings in the controller log other than one device being powered off (see below).Environment
mediatek/filogic, OpenWrt SNAPSHOT r35063-7edb29d241. Shared PHY:phy0.0-ap0(2.4 GHz) andphy0.1-ap0(5 GHz) both onphy0, configured asradio0andradio1.Results
capability probe found no changes device=0c:85:09:03:05:50 automatic=false. The stored radios are:Device phy0.0-ap0,Phy phy0,Section radio0, band 2g, channel 1Device phy0.1-ap0,Phy phy0,Section radio1, band 5g, channel 52Both on one PHY, with distinct UCI sections, hardware
MediaTek MT7992E.completed,router_outcome: applied,outcome: applied,changes: 0,write_state: none, reason "already matches the site model; nothing to do", no error. NoUNIQUE constraint failed: owned_sections— that is exactly where the original apply stopped.wireless.oowrt_wlan2_radio0andwireless.oowrt_wlan2_radio1(8 rows for 4 devices, no duplicates).wifi-ifacesections unchanged and referencingradio0/radio1respectively; both bands broadcasting (channel 1 with 10 clients, channel 52 with 8 clients);hostapdreportsENABLEDon both BSSes; the apply triggered no hostapd or netifd events.One honest limitation
My own v0.1.5 patch had already written the two correct sections to this router, so this build had nothing left to write. The run therefore exercised probing, rendering, validation, the apply path and ownership recording — but not a fresh write of the sections. What it does show is that the PR build renders the two bands to distinct UCI sections and agrees with a router that already has them: had it still collapsed both onto
radio0, the preview would have proposed rewriting or dropping the second section, and it does not.If you want the write path exercised from a clean slate on this hardware, say so and I can arrange a controlled run.
Verdict: confirmed working on the affected hardware. Thanks for the quick turnaround.
Testing, evidence collection and this write-up done with Claude Code, same as the original report; the hardware runs, the re-probe and the apply were mine.
aiden0rchad commentedon Sep 18, 2026
v0.1.8 is now published with the shared-PHY radio-identity fix from #42: release and downloads.
The prebuilt container is
ghcr.io/aiden0rchad/oonfeewrt:v0.1.8for Linux amd64/arm64; standalone Linux and macOS binaries are also attached to the release.Thank you, @flubba, for the detailed diagnosis and for verifying the exact PR build on the BE12 Pro. Your successful re-probe, repeated Preview, no-op Apply, and distinct ownership rows are valuable confirmation. That test used configuration corrected by your earlier patch, so we are not presenting it as a fresh-write hardware test. Our WRT3200ACM and Archer C6 checks were read-only and also proposed no changes.
After taking the documented upgrade backup, please verify the official v0.1.8 build: re-probe the affected device, then generate a fresh Preview and confirm the distinct UCI radio targets. Apply only if the plan is intended and it is safe to change the router. There is no need to undo a working configuration just to test this release, clear ownership rows, reset the database, or re-adopt.
Could you confirm whether the released build resolves this issue? If a normal, planned configuration change later exercises fresh writes on the shared-PHY device, that result would also be helpful. Please share any remaining error and sanitized probe/Preview evidence, without credentials, wireless keys, or network identifiers. Leaving this issue open pending your release verification.
aiden0rchad commentedon Sep 18, 2026
Thanks again, @flubba, for the detailed report and verification of the exact PR build. Closing the reported radio-target collapse and ownership-recording error as fixed by #42, now shipped in v0.1.8.
The hardware evidence covers re-probe, Preview, no-op Apply, and distinct ownership records—not fresh configuration writes on shared-PHY hardware. That limitation remains documented; there is no need to undo a working setup solely for testing.
If the problem persists on v0.1.8 after re-probing and reviewing a fresh Preview, please comment with sanitized evidence and we can reopen this issue. Do not reset the database or clear ownership records as a workaround.