fix(spine): nil-check remoteFeature in SubscribeToRemote/BindToRemote (minimal patch for #87)#90
Open
terabytegmbh wants to merge 1 commit into
Open
Conversation
FeatureByAddress() can return nil when a remote device advertises a
feature address that is not yet materialized in the local entity model.
The two existing call sites in FeatureLocal then call
remoteFeature.Type() / remoteFeature.Role() unconditionally, panicking
with a nil-pointer dereference. The panic happens in the goroutine
created by spine.(*events).Publish, so downstream callers cannot
recover from it.
Reproduced reliably during eebus-go EG-LPC use case startup, when
lpc.(*LPC).connected() runs Subscribe() before the remote has finished
publishing its LoadControl feature:
panic: runtime error: invalid memory address or nil pointer dereference
spine.(*FeatureLocal).SubscribeToRemote(...)
spine/feature_local.go:451
eebus-go/features/client.(*Feature).Subscribe(...)
eebus-go/usecases/eg/lpc.(*LPC).connected(...)
usecases/eg/lpc/events.go:76
created by spine.(*events).Publish
Fix mirrors the existing nil-check pattern used immediately above (for
remoteAddress.Device and remoteDevice): return a proper *model.ErrorType
("feature not found") that calling code already handles as a debug-level
non-fatal event.
Includes test cases TestSubscribeToRemote_NilFeature and
TestBindToRemote_NilFeature that construct an unknown feature address
and assert no-panic + non-nil error.
Scope: 6 production lines + 2 test cases. No behavioural change for
the non-nil path.
Signed-off-by: Thomas Quien <thomas.quien@terabyte-gmbh.de>
Made-with: Cursor
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.
Fixes #87. Minimal-scope alternative to #88.
Problem
FeatureLocal.SubscribeToRemoteandBindToRemotedereferenceremoteDevice.FeatureByAddress()without a nil-check. When a remote device advertises a feature address that the local entity model has not yet materialized,FeatureByAddressreturnsniland the subsequent.Type()/.Role()call panics inside thespine.(*events).Publishgoroutine, killing the process.Reproduced reliably in
eebus-goEG-LPC use case startup:lpc.(*LPC).connected()runsSubscribe()while the remote'sLoadControlfeature has not yet been published.Fix
Mirror the existing nil-check pattern used immediately above (for
remoteAddress.DeviceandremoteDevice): return a proper*model.ErrorType("feature not found")that the calling code already handles as a debug-level non-fatal event.Scope
spine/feature_local.goTestSubscribeToRemote_NilFeature,TestBindToRemote_NilFeature)Relation to #88
#88 from @SAY-5 also addresses #87 with the same conceptual approach (nil-check + early error return), but additionally contains a wider refactor (199 changed files, +23573/-4189 LoC). The maintainer may prefer either path:
Happy to defer to whichever direction you'd like to land — the issue itself is what matters.
Test
go test ./spine/...clean. Two new tests verify the error-returning path is taken whenFeatureByAddressreturns nil.Provenance
Patch has been running in our internal
synervatt/spine-gofork since 2026-04-21 without regressions in theeebus-goEG-LPC integration path.— Thomas, Terabyte GmbH