Repository navigation
Conversation
ValidatePattern built its regexp with MustCompile from a {r:N:cs} length
it never checked. Go's regexp refuses a repeat count above 1000, so a
template such as call_{r:1001:x} panicked. The template comes verbatim
from the model's submit_pattern call, and the panic happens in the flow
prepare goroutine, where no recover runs, so one such answer stopped the
whole process. A heuristic fallback built from IDs longer than 1000
characters was stored in flows.tool_call_id_template and panicked again
on every restart that resumed the flow.
parsePattern now rejects a length that does not parse or exceeds the
regexp limit, ValidatePattern returns that error instead of panicking,
GenerateFromPattern falls back to the default template, the heuristic
fallback yields nothing for a pattern it cannot compile, and
toolCallIDTemplateOrDefault replaces a stored template that no longer
compiles with the default.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QCjnWfCbd1hMpiS7wwkQPc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description of the Change
Problem
templates.ValidatePatternbuilds a regexp from the tool-call-ID template and compiles it withregexp.MustCompile. The{r:N:cs}length is read withstrconv.Atoiand the error is discarded. Go's regexp refuses a repeat count above 1000, so a template such ascall_{r:1001:x}, or one whose count overflowsint, panics.The template is taken verbatim from the model's
submit_patterntool call indetectPatternWithAI(backend/pkg/providers/provider/agents.go). The panic happens insidego fc.prepareFlow(...), where norecoverruns, so one such answer stops the whole process and every running flow with it. A user withsettings.prompts.editcan cause this by editing thetool_call_id_detectorprompt, and an OpenAI-compatible endpoint can cause it by answering with that template or with IDs longer than 1000 characters.The heuristic fallback has the same gap: it derives
{r:N:cs}from the sample IDs and stores it unvalidated. The template is written toflows.tool_call_id_template, and on restartrestoreChain→NormalizeToolCallIDs→ValidatePatternpanics again for every tool call in the chain.Solution
parsePatternreturns an error when the length does not parse or exceeds the regexp limit (1000).ValidatePatternreturns that error and compiles withregexp.Compileinstead ofMustCompile.GenerateFromPatternkeeps its no-error contract and falls back toDefaultToolCallIDTemplatefor a pattern that does not compile.cast.ToolCallIDTemplatenow points at that constant.fallbackHeuristicDetectionyields""for a pattern it cannot compile, so the caller takes the default.toolCallIDTemplateOrDefaultreplaces a stored template that no longer compiles with the default, which also repairs rows written before this change.templates.ValidatePatternSyntaxis the one exported check the last two use.Reproduction of the panic before the fix (Go 1.24.7):
Type of Change
Areas Affected
Testing and Verification
Test Steps
cd backend && go test -race -count=1 ./pkg/templates/ ./pkg/cast/ ./pkg/providers/provider/ ./pkg/providers/go vet,gofmt -landgolangci-lint run(v2.12.2, the CI pin) on the same packages.Test Results
New tests: two rows in
TestTemplates_ValidatePattern_NamesWhereASampleDiverges,TestTemplates_ValidatePatternSyntax_StopsAtTheLargestRepeatTheRegexpCompiles,TestTemplates_GenerateFromPattern_FallsBackToTheDefaultTemplateWhenThePatternCannotCompile, a row inTestAgents_FallbackHeuristicDetection_BuildsThePatternTheSamplesShareand a row inTestHelpers_ToolCallIDTemplateOrDefault_NeverYieldsAnEmptyTemplate.pkg/templates,pkg/cast,pkg/providers/providerandpkg/providerspass under-race;golangci-lintreports 0 issues. The one exception:TestPerformer_AiResponsePart_ReplaysATextlessThinkingTurnOnTheClaudeDoors/bedrock/*fails on unmodifiedmainin my environment too (unable to add custom RootCAs HTTPClient, an AWS SDK config error caused by the sandbox's HTTP proxy) and was skipped. No dependency changed, sogo mod tidyleavesgo.modandgo.sumas they are.Security Considerations
Removes a remote denial of service: a prompt edit by a low-privilege user, or a hostile LLM endpoint, could crash the server and leave a flow that crashes it again on every restart. No new dependencies, no permission changes.
Performance Impact
None. One extra parse of the template on flow and assistant creation.
Deployment Notes
None. A flow whose stored template no longer compiles falls back to
call_{r:24:x}on load and its chain IDs are normalised to it.Additional Notes
A
recoverin the flow prepare and worker goroutines would turn any future panic into a failed flow instead of a dead process. It is left out of this PR to keep the change to the bug.