Skip to content

[Go] panic: action "/model/googleai/gemini-2.5-flash" is already registered [recovered, repanicked] #3580

@janishorsts

Description

@janishorsts

Describe the bug

When executing the genkit flows in parallel, the registry panics with `panic: action "/model/googleai/gemini-2.5-flash" is already registered [recovered, repanicked].

I assume the model registration is a long-running process by making the HTTP request(s). Effectively, allowing multiple registrations for the same model to start when it is not registered, with the first completed one succeeding and the remaining ones failing.

To Reproduce

package main

import (
	"context"
	"fmt"
	"log/slog"
	"testing"

	"github.com/firebase/genkit/go/ai"
	"github.com/firebase/genkit/go/genkit"
	"github.com/firebase/genkit/go/plugins/googlegenai"
	"golang.org/x/sync/errgroup"
)

type Input struct {
	Message string `json:"message"`
}

type Output struct {
	Message string `json:"message"`
}

func TestActionAlreadyRegistered(t *testing.T) {
	slog.SetLogLoggerLevel(slog.LevelDebug)

	ctx := t.Context()
	g := genkit.Init(ctx,
		genkit.WithPlugins(new(googlegenai.GoogleAI)),
		genkit.WithDefaultModel("googleai/gemini-2.5-flash"),
	)

	prompt := genkit.DefinePrompt(g, "ping-pong", ai.WithSystem("Play ping pong with me!"))

	f := genkit.DefineFlow(g, "ping-pong", func(ctx context.Context, input Input) (Output, error) {
		res, err := prompt.Execute(ctx, ai.WithMessages(ai.NewUserTextMessage(input.Message)))
		if err != nil {
			return Output{}, fmt.Errorf("ping: %w", err)
		}

		return Output{res.Message.Text()}, nil
	})

	eg, egCtx := errgroup.WithContext(ctx)

	
	for range 2 {
		eg.Go(func() error {
			// this triggers the model registration in parallel and panics
			res, err := f.Run(egCtx, Input{"ping"})
			t.Log(res.Message)
			return err
		})
	}

	err := eg.Wait()
	if err != nil {
		t.Fatalf("want no error, got %v", err)
	}
}

Expected behavior

No panic.

Screenshots

Running tool: /opt/homebrew/Cellar/go/1.25.1/libexec/bin/go test -timeout 30s x -v

=== RUN   TestActionAlreadyRegistered
2025/09/15 21:48:26 DEBUG RegisterPlugin name=googleai
2025/09/15 21:48:26 DEBUG RegisterValue name=/format/json
2025/09/15 21:48:26 DEBUG RegisterValue name=/format/jsonl
2025/09/15 21:48:26 DEBUG RegisterValue name=/format/text
2025/09/15 21:48:26 DEBUG RegisterValue name=/format/array
2025/09/15 21:48:26 DEBUG RegisterValue name=/format/enum
2025/09/15 21:48:26 DEBUG RegisterAction key=/util/generate
2025/09/15 21:48:26 DEBUG Default prompt directory not found, skipping loading .prompt files dir=./prompts
2025/09/15 21:48:26 DEBUG RegisterValue name=genkit/defaultModel
2025/09/15 21:48:26 DEBUG RegisterValue name=genkit/promptDir
2025/09/15 21:48:26 DEBUG RegisterAction key=/executable-prompt/ping-pong
2025/09/15 21:48:26 DEBUG RegisterAction key=/flow/ping-pong
2025/09/15 21:48:26 DEBUG Action.Run name=0x104f72020 input="main.Input{Message:\"ping\"}"
2025/09/15 21:48:26 DEBUG span start name=ping-pong
2025/09/15 21:48:26 DEBUG Action.Run name=0x104f72020 input="main.Input{Message:\"ping\"}"
2025/09/15 21:48:26 DEBUG span start name=ping-pong
2025/09/15 21:48:26 DEBUG Action.Run name=0x104d1a210 input="map[string]interface {}(nil)"
2025/09/15 21:48:26 DEBUG span start name=ping-pong
2025/09/15 21:48:26 DEBUG Action.Run name=0x104d1a210 input="map[string]interface {}(nil)"
2025/09/15 21:48:26 DEBUG span start name=ping-pong
2025/09/15 21:48:26 DEBUG span end name=ping-pong
2025/09/15 21:48:26 DEBUG Action.Run name=0x104d1a200 output="api.ActionRunResult[*github.com/firebase/genkit/go/ai.GenerateActionOptions]{Result:(*ai.GenerateActionOptions)(0x1400012a210), TraceId:\"454e3fc57ca067a92bf161b80537af1a\", SpanId:\"10bc24ae81180d7a\"}" err=<nil>
2025/09/15 21:48:26 DEBUG span end name=ping-pong
2025/09/15 21:48:26 DEBUG Action.Run name=0x104d1a200 output="api.ActionRunResult[*github.com/firebase/genkit/go/ai.GenerateActionOptions]{Result:(*ai.GenerateActionOptions)(0x140001dcb00), TraceId:\"2fde2252cce6b18240c3a0c1d791f1f4\", SpanId:\"dbbe961b0ab9993c\"}" err=<nil>
2025/09/15 21:48:26 DEBUG RegisterAction key=/model/googleai/gemini-2.5-flash
2025/09/15 21:48:26 DEBUG span start name=generate
2025/09/15 21:48:26 DEBUG Action.Run name=0x104d184d0 input="&ai.ModelRequest{Config:interface {}(nil), Docs:[]*ai.Document(nil), Messages:[]*ai.Message{(*ai.Message)(0x140001267b0), (*ai.Message)(0x140001264b0)}, Output:(*ai.ModelOutputConfig)(0x140003c9e90), ToolChoice:\"\", Tools:[]*ai.ToolDefinition{}}"
2025/09/15 21:48:26 DEBUG span start name=googleai/gemini-2.5-flash
2025/09/15 21:48:26 DEBUG span end name=ping-pong
2025/09/15 21:48:26 DEBUG Action.Run name=0x104f72010 output="api.ActionRunResult[x.Output]{Result:main.Output{Message:\"\"}, TraceId:\"\", SpanId:\"\"}" err=<nil>
panic: action "/model/googleai/gemini-2.5-flash" is already registered [recovered, repanicked]

goroutine 40 [running]:
go.opentelemetry.io/otel/sdk/trace.(*recordingSpan).End.deferwrap1()
	/Users/foobar/go/pkg/mod/go.opentelemetry.io/otel/[email protected]/trace/span.go:467 +0x28
go.opentelemetry.io/otel/sdk/trace.(*recordingSpan).End(0x14000400000, {0x0, 0x0, 0x14000400000?})
	/Users/foobar/go/pkg/mod/go.opentelemetry.io/otel/[email protected]/trace/span.go:500 +0x93c
panic({0x10519cf00?, 0x14000780db0?})
	/opt/homebrew/Cellar/go/1.25.1/libexec/src/runtime/panic.go:783 +0x120
github.com/firebase/genkit/go/internal/registry.(*Registry).RegisterAction(0x140002b9480, {0x140001d8280, 0x20}, {0x105346e60, 0x14000780d90})
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/internal/registry/registry.go:95 +0x204
github.com/firebase/genkit/go/core.(*ActionDef[...]).Register(...)
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/action.go:321
github.com/firebase/genkit/go/internal/registry.(*Registry).ResolveAction(0x140002b9480, {0x140005c0020, 0x20})
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/internal/registry/registry.go:181 +0x1e0
github.com/firebase/genkit/go/core.ResolveActionFor[...]({0x10534fd20, 0x140002b9480}, {0x104fc1bfc, 0x5}, {0x104fd6332, 0x140002b9480?})
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/action.go:330 +0x7c
github.com/firebase/genkit/go/ai.LookupModel({0x10534fd20?, 0x140002b9480?}, {0x104fd6332?, 0x0?})
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/ai/generate.go:197 +0x4c
github.com/firebase/genkit/go/ai.GenerateWithRequest({0x1053443f8, 0x140003fc420}, {0x10534fd20, 0x140002b9480}, 0x140001dcb00, {0x0, 0x0, 0x0?}, 0x0)
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/ai/generate.go:217 +0xe0
github.com/firebase/genkit/go/ai.(*prompt).Execute(0x140003cab40, {0x1053443f8, 0x140003fc420}, {0x140004021b0, 0x1, 0x10491176c?})
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/ai/prompt.go:183 +0x348
x.TestActionAlreadyRegistered.func1({0x1053443f8, 0x140003fc420}, {{0x104fc10ee?, 0x14000191f78?}})
	/Users/foobar/projects/playground/genkit-err/x_test.go:35 +0x25c
github.com/firebase/genkit/go/core.DefineFlow[...].func1({{0x104fc10ee, 0x104f71cc0}})
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/flow.go:53 +0x80
github.com/firebase/genkit/go/core.DefineAction[...].func1({{0x104fc10ee?, 0x10519d5c0?}}, 0x140001f7701?)
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/action.go:95 +0x30
github.com/firebase/genkit/go/core.newAction[...].func1({{0x104fc10ee?, 0x30?}}, 0x14000082808?)
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/action.go:158 +0x30
github.com/firebase/genkit/go/core.(*ActionDef[...]).runWithTelemetry.func3({{0x104fc10ee, 0x14000191f68}})
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/action.go:227 +0x134
github.com/firebase/genkit/go/core/tracing.RunInNewSpan[...]({0x105344430, 0x140001fbea0}, 0x140001f7d30, {{0x104fc10ee, 0xa?}}, 0x140001f7df0?)
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/tracing/tracing.go:245 +0xcb0
github.com/firebase/genkit/go/core.(*ActionDef[...]).runWithTelemetry(0x105354180, {0x105344430, 0x140001fbea0}, {{0x104fc10ee, 0x0?}}, 0x0?)
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/action.go:214 +0x2bc
github.com/firebase/genkit/go/core.(*ActionDef[...]).Run(0x0?, {0x105344430?, 0x140001fbea0?}, {{0x104fc10ee?, 0x0?}}, 0x0?)
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/action.go:177 +0x30
github.com/firebase/genkit/go/core.(*Flow[...]).Run(...)
	/Users/foobar/go/pkg/mod/github.com/firebase/genkit/[email protected]/core/flow.go:123
x.TestActionAlreadyRegistered.func2()
	/Users/foobar/projects/playground/genkit-err/x_test.go:47 +0x44
golang.org/x/sync/errgroup.(*Group).Go.func1()
	/Users/foobar/go/pkg/mod/golang.org/x/[email protected]/errgroup/errgroup.go:93 +0x4c
created by golang.org/x/sync/errgroup.(*Group).Go in goroutine 36
	/Users/foobar/go/pkg/mod/golang.org/x/[email protected]/errgroup/errgroup.go:78 +0x90
FAIL	x	0.274s

Runtime:

  • OS: MacOS
  • Version: 15.6.1 (24G90)
  • Genkit Go: v1.0.3

Go version

$ go version
go version go1.25.1 darwin/arm64

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinggo

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions