Skip to content

Conversation

@Zereker
Copy link

@Zereker Zereker commented Dec 11, 2025

Summary

  • Fix template sharing bug in Compile() method where all compiled PromptFunction closures shared the same dp.Template
  • Add regression test TestCompileMultiplePromptsTemplateIsolation to prevent future regressions

Problem

When using the Compile() method multiple times on the same Dotprompt instance, all compiled PromptFunction closures share the same dp.Template field. This causes subsequent prompt executions to use the wrong template.

Root Cause

In dotprompt.go, the Compile method:

  1. Creates a new renderTpl from parsing the source
  2. Stores it to the shared dp.Template field via initializeTemplate()
  3. Returns a closure renderFunc that references dp.Template

When another prompt is compiled, dp.Template gets overwritten, causing all previous renderFunc closures to use the wrong template.

Example

dp := dotprompt.NewDotprompt(nil)

prompt1, _ := dp.Compile("Talk about weather: {{topic}}", nil)
prompt2, _ := dp.Compile("Talk about programming: {{language}}", nil)

// BUG: prompt1 uses prompt2's template!
result1, _ := prompt1(&DataArgument{Input: map[string]any{"topic": "sunny"}}, nil)
// Expected: "Talk about weather: sunny"
// Actual: "Talk about programming: sunny"

Solution

Capture the current template in a local variable before creating the closure:

localTemplate := dp.Template

renderFunc := func(...) {
    renderedString, err := localTemplate.ExecWith(...)  // Use local template
    ...
}

Test Plan

  • Added TestCompileMultiplePromptsTemplateIsolation regression test
  • All existing tests pass
  • Verified fix resolves the issue in real-world usage (Firebase Genkit Go SDK)

Fixes #362

@google-cla
Copy link

google-cla bot commented Dec 11, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@Zereker
Copy link
Author

Zereker commented Dec 11, 2025

I have signed the CLA.

The Compile() method was storing the parsed template in dp.Template and
referencing it in the returned closure. When multiple prompts were compiled
on the same Dotprompt instance, all closures would share the same dp.Template,
causing subsequent prompts to use the wrong template.

This fix captures the current template in a local variable before creating
the closure, ensuring each compiled PromptFunction uses its own template.

Fixes google#362
@Zereker Zereker force-pushed the fix/compile-template-sharing-bug branch from 175e440 to 21db81b Compare December 11, 2025 12:09
@Zereker
Copy link
Author

Zereker commented Dec 11, 2025

Test Results

I tested this fix with the memory project using replace directive:

replace github.com/google/dotprompt/go => /tmp/dotprompt/go

Unit test in dotprompt package: ✅ PASS

=== RUN   TestCompileMultiplePromptsTemplateIsolation
--- PASS: TestCompileMultiplePromptsTemplateIsolation (0.00s)

Note: The fix resolves the template sharing issue when compiling multiple different prompts on the same Dotprompt instance. There may be additional caching issues in firebase/genkit when using LookupPrompt with the same .prompt file multiple times, but that would be a separate issue in the genkit repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Compile() method shares Template field across multiple prompts causing wrong template execution

2 participants