Go Module Dependency Pinning
When developing your server runtime code with Go it is important to be aware of the way the Go plugin module is loaded into the Layerg binary and what constraints this places on your runtime module. Since Go is a compiled and linked language, it is strict about how the final binary is put together. It is for this reason that the server runtime plugin you compile must be compiled in the same way as the Layerg server binary you are using. This imposes a few restrictions which can result in several common errors if they are not met.
Below are some of the common pitfalls you may encounter when developing your server runtime code using Go and how to effectively solve them.
Platform Mismatch
Problem
You will encounter an issue when attempting to load a server runtime Go module that has been compiled using a different platform than the Layerg binary itself. For example, you cannot use a Go module that has been compiled on Linux together with a Layerg binary that has been compiled on macOS.
{
"level":"error",
"ts":"...",
"caller":"...",
"msg":"Error initialising Go runtime provider",
"error":"plugin.Open(\"/layerg/data/modules/backend.so\"): /layerg/data/modules/backend.so: invalid ELF header"
}
Solution
Ensure the platform you are compiling the Go server runtime module for matches the platform that the Layerg binary was compiled for.
Go Runtime Version Mismatch
Problem
You will encounter an issue when attempting to load a server runtime Go module that has been compiled using a different version of the Go Runtime than the Layerg binary itself. For example, you cannot use a Go module that has been compiled with Go version 1.14 together with a Layerg binary that has been compiled with Go version 1.15.
{
"level":"error",
"ts":"...",
"caller":"...",
"msg":"Could not open Go module",
"path":"/layerg/data/modules/backend.so",
"error":"plugin.Open(\"/layerg/data/modules/backend\"): plugin was built with a different version of package runtime/internal/sys"
}
Solution
Go Dependency Version Mismatch
Problem
Any dependency/package you use, either directly or indirectly (transitive dependencies), that are also used by the Layerg binary, must be the same version. For example, if you are using version 3.3.0
of the github.com/gofrs/uuid
package in your server runtime module and the Layerg binary is using the 4.0.0
version, then you will encounter a dependency version mismatch error.
{
"level":"fatal",
"ts":"...",
"caller":"...",
"msg":"Failed initializing runtime modules",
"error":"plugin.Open(\"/layerg/data/modules/backend\"): plugin was built with a different version of package go.uber.org/zap/buffer"
}
Solution
Ensure you are using the same dependency/package versions as the Layerg binary you intend to run your server runtime module on.
Where the mismatch occurs with a direct dependency, you must ensure you are importing the exact version that is used by Layerg in your go.mod
file.
In a situation where the dependency mismatch is on an indirect (transitive) dependency, you can ensure you are using the same version by explicitly importing the dependency in your go.mod
file, then adding a blank import statement using an _
(underscore) alias to make it a direct dependency as seen in the example below.
import (
_ "go.uber.org/zap"
)
Once you have done this, you can run the go mod vendor
command to vendor your dependencies again and ensure you are now using the appropriate version.
go.mod
file by searching LayerG's vendor/modules.txt
file and look for the package that lead to the error.This method may take some trial and error as Layerg implements the fail fast methodology whereby the server will throw an error and shutdown at the first error it encounters with your server runtime code. This means that if there are several dependency version mismatches, you may need to fix them one at a time.