From 347ab5b3480db6c698292ad9773f45cd2be5408f Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 28 Aug 2025 12:58:02 +0100 Subject: [PATCH] fix(coderd/taskname): ensure generated name is within 32 byte limit (#19612) The previous logic verified a generated name was valid, _and then appended a suffix to it_. This was flawed as it would allow a 32 character name, and then append an extra 5 characters to it. Instead we now append the suffix _and then_ verify it is valid. --- coderd/taskname/taskname.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/coderd/taskname/taskname.go b/coderd/taskname/taskname.go index dff57dfd0c..734c23eb3d 100644 --- a/coderd/taskname/taskname.go +++ b/coderd/taskname/taskname.go @@ -24,7 +24,7 @@ const ( Requirements: - Only lowercase letters, numbers, and hyphens - Start with "task-" -- Maximum 28 characters total +- Maximum 27 characters total - Descriptive of the main task Examples: @@ -145,17 +145,23 @@ func Generate(ctx context.Context, prompt string, opts ...Option) (string, error return "", ErrNoNameGenerated } - generatedName := acc.Messages()[0].Content - - if err := codersdk.NameValid(generatedName); err != nil { - return "", xerrors.Errorf("generated name %v not valid: %w", generatedName, err) - } - - if generatedName == "task-unnamed" { + taskName := acc.Messages()[0].Content + if taskName == "task-unnamed" { return "", ErrNoNameGenerated } - return fmt.Sprintf("%s-%s", generatedName, generateSuffix()), nil + // We append a suffix to the end of the task name to reduce + // the chance of collisions. We truncate the task name to + // to a maximum of 27 bytes, so that when we append the + // 5 byte suffix (`-` and 4 byte hex slug), it should + // remain within the 32 byte workspace name limit. + taskName = taskName[:min(len(taskName), 27)] + taskName = fmt.Sprintf("%s-%s", taskName, generateSuffix()) + if err := codersdk.NameValid(taskName); err != nil { + return "", xerrors.Errorf("generated name %v not valid: %w", taskName, err) + } + + return taskName, nil } func anthropicDataStream(ctx context.Context, client anthropic.Client, model anthropic.Model, input []aisdk.Message) (aisdk.DataStream, error) {