In my quest to build a multiplayer video game using Nakama, I came across this pesky error.

{"level":"fatal","ts":"2026-04-16T02:35:38.426Z","caller":"server/runtime_go.go:3079","msg":"Error reading InitModule function in Go module","name":"backend"}

WTF is this? there is so little information.

Let’s look at my main.go.

package main
 
import (
	"context"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
 
	"fiatjaf.com/nostr"
	"github.com/heroiclabs/nakama-common/api"
	"github.com/heroiclabs/nakama-common/runtime"
)
 
const (
	OK                  = 0
	CANCELED            = 1
	UNKNOWN             = 2
	INVALID_ARGUMENT    = 3
	DEADLINE_EXCEEDED   = 4
	NOT_FOUND           = 5
	ALREADY_EXISTS      = 6
	PERMISSION_DENIED   = 7
	RESOURCE_EXHAUSTED  = 8
	FAILED_PRECONDITION = 9
	ABORTED             = 10
	OUT_OF_RANGE        = 11
	UNIMPLEMENTED       = 12
	INTERNAL            = 13
	UNAVAILABLE         = 14
	DATA_LOSS           = 15
	UNAUTHENTICATED     = 16
)
 
var (
	errBadInput      = runtime.NewError("input contained invalid data", INVALID_ARGUMENT)
	errInternalError = runtime.NewError("internal server error", INTERNAL)
)
 
func authCustomHandlerBefore(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateCustomRequest) (*api.AuthenticateCustomRequest, error) {
	token := in.Account.Id
	logger.Info(fmt.Sprintf(">> Handling custom auth for account.id=%s (that's actually a nip98 token, length=%d)", token, len(token)))
 
	decoded, err := base64.StdEncoding.DecodeString(token)
	if err != nil {
		logger.Error("failed to base64 decode token: %v", err)
		return nil, errBadInput
	}
	logger.Info(fmt.Sprintf(">> Decoded token to JSON (length=%d)", len(decoded)))
 
	var event nostr.Event
	err = json.Unmarshal(decoded, &event)
	if err != nil {
		logger.Error("failed to parse JSON: %v", err)
		return nil, errBadInput
	}
	logger.Info(fmt.Sprintf(">> Parsed Nostr event: kind=%d, pubkey=%s", event.Kind, event.PubKey))
 
	if !event.VerifySignature() {
		logger.Error("invalid signature on Nostr event")
		return nil, errBadInput
	}
	logger.Info(">> Signature verified successfully")
 
	if event.Kind != 27235 {
		logger.Error(fmt.Sprintf("expected NIP-98 event (kind 27235), got kind %d", event.Kind))
		return nil, errBadInput
	}
 
	userId := event.PubKey.Hex()
	logger.Info(fmt.Sprintf(">> Using pubkey as userId: %s", userId))
 
	in.Account.Id = userId
	return in, nil
}
 
func authCustomHandlerAfter(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, out *api.Session, in *api.AuthenticateCustomRequest) error {
	return nil
}
 
func guardApple(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateAppleRequest) (*api.AuthenticateAppleRequest, error) {
	return in, nil
}
 
func guardDevice(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateDeviceRequest) (*api.AuthenticateDeviceRequest, error) {
	return in, nil
}
 
func guardEmail(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateEmailRequest) (*api.AuthenticateEmailRequest, error) {
	return in, nil
}
 
func guardFacebook(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateFacebookRequest) (*api.AuthenticateFacebookRequest, error) {
	return in, nil
}
 
func guardFacebookInstantGame(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateFacebookInstantGameRequest) (*api.AuthenticateFacebookInstantGameRequest, error) {
	return in, nil
}
 
func guardGameCenter(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateGameCenterRequest) (*api.AuthenticateGameCenterRequest, error) {
	return in, nil
}
 
func guardGoogle(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateGoogleRequest) (*api.AuthenticateGoogleRequest, error) {
	return in, nil
}
 
func guardSteam(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateSteamRequest) (*api.AuthenticateSteamRequest, error) {
	return in, nil
}
 
func InitModule(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, initializer runtime.Initializer) error {
	initializer.RegisterBeforeAuthenticateCustom(authCustomHandlerBefore)
	initializer.RegisterAfterAuthenticateCustom(authCustomHandlerAfter)
 
	initializer.RegisterBeforeAuthenticateApple(guardApple)
	initializer.RegisterBeforeAuthenticateDevice(guardDevice)
	initializer.RegisterBeforeAuthenticateEmail(guardEmail)
	initializer.RegisterBeforeAuthenticateFacebook(guardFacebook)
	initializer.RegisterBeforeAuthenticateFacebookInstantGame(guardFacebookInstantGame)
	initializer.RegisterBeforeAuthenticateGameCenter(guardGameCenter)
	initializer.RegisterBeforeAuthenticateGoogle(guardGoogle)
	initializer.RegisterBeforeAuthenticateSteam(guardSteam)
 
	return nil
}
 

What is this file? It’s a customized Nakama runtime, as described in their guide. https://heroiclabs.com/docs/nakama/server-framework/go-runtime

I need to customize my Nakama auth flow, so players can log in using Nostr NIP-98. The idea is that the players log in locally using their window.nostr compatible extension, then generate a NIP-98 nostr event and send it to Nakama server. Using fiatjaf.com/nostr go module, we validate the event. If the event is valid, that means the user is who they say they are, and we log in the player.

That’s the idea, but something is WRONG with my go code. I’m a golang noob so I’m probably doing something wrong, but this is apparently so wrong that even a LLM can’t fix it. I gotta break it down, write it down, and systematically figure out the root cause so I can move forward. That’s the purpose of this document.

First of all, we search the forum for the error we are seeing.

https://forum.heroiclabs.com/search?q=Error%20reading%20InitModule%20function%20in%20Go%20module

{"level":"fatal","ts":"2026-04-16T02:35:38.426Z","caller":"server/runtime_go.go:3079","msg":"Error reading InitModule function in Go module","name":"backend"}

Oh look at that, we got matching results!

The InitModule func should have the following signature:
InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, iz runtime.Initializer) error https://forum.heroiclabs.com/t/failed-initializing-runtime-modules-plugin-was-built-with-a-different-version-of-package-google-golang-org-protobuf-internal-pragma/3265/6?u=grimtechnet

Well that explains it! My function signature was wrong.

func InitModule(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, initializer runtime.Initializer) error {

I fixed that, rebuilt, deployed, and the Nakama runtime was stable and healthy.