Symptom

Production deb 1.0.891 (the post-#164 release) still couldn’t reach krill-pi4j. The new defensive logging from the #164 follow-up surfaced the real cause this time:

1
2
3
Failed to initialize krill-pi4j gRPC client on localhost:50051. ...
java.lang.IllegalArgumentException: Address types of NameResolver 'unix' for 'localhost:50051' not supported by transport
WARN  - getAllPins: krill-pi4j client unavailable, returning empty header

/header still returned [], all GPIO operations were no-ops.

Root cause

shadowJar’s default duplicatesStrategy = EXCLUDE silently drops the second copy of any duplicated file path before it reaches a configured transformer. META-INF/services/io.grpc.NameResolverProvider exists in two artifacts on the runtime classpath:

Whichever one Gradle’s copy task processed first won; the other was excluded. The shipped jar therefore registered only the unix-domain resolver. When Pi4jClient called ManagedChannelBuilder.forAddress("localhost", 50051), gRPC picked unix: as the only available scheme and the Netty TCP transport rejected the resulting DomainSocketAddress. lateinit var client never got assigned, the post-#164 short-circuit kicked in for every method, and the hardware bridge remained silent.

The same trap applies to every other ServiceLoader-using library on the classpath (LoadBalancerProvider, ServerProvider, JDBC, kotlinx-serialization, …). #164 fixed the class-stripping axis of this problem; #168 fixes the service-file-merge axis.

Fix

Prevention

The build-time assertion is the load-bearing prevention. Two distinct packaging regressions (classes pruned by minimize, service files dropped by duplicatesStrategy) presented identically as /header returning [] and silent GPIO; the assertion now catches both. New runtime dependencies that bring service files don’t need any further config — the INCLUDE + mergeServiceFiles combination handles them automatically — but if a future gRPC version adds a new required provider line, the assertion list at the top of the doLast block needs to grow with it.