fix(coderd/provisionerdserver): clarify duplicate preset errors (#28530)

> 🤖 This PR was written by Coder Agents on behalf of Jake Howell.

Template imports with duplicate preset names currently expose the
underlying PostgreSQL unique constraint error.

Translate that constraint violation into a clear validation message that
identifies the duplicate preset name.

<img width="1110" height="462" alt="image"
src="https://github.com/user-attachments/assets/dc7b86a3-8f85-4694-a0be-aea3d0b53360"
/>


Closes https://github.com/coder/coder/issues/19270
This commit is contained in:
Jake Howell
2026-08-26 11:00:31 +07:00
committed by GitHub
parent 5008603d08
commit bd4af31f78
2 changed files with 33 additions and 0 deletions
@@ -2979,6 +2979,9 @@ func InsertWorkspacePresetAndParameters(ctx context.Context, db database.Store,
return nil
}, nil)
if database.IsUniqueViolation(err, database.UniqueIndexUniquePresetName) {
return xerrors.Errorf("duplicate preset name, must be unique per template: %q", protoPreset.Name)
}
if err != nil {
return xerrors.Errorf("insert preset and parameters: %w", err)
}
@@ -4009,6 +4009,36 @@ func TestInsertWorkspacePresetsAndParameters(t *testing.T) {
}
})
}
t.Run("duplicate preset names", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
logger := testutil.Logger(t)
db, ps := dbtestutil.NewDB(t)
org := dbgen.Organization(t, db, database.Organization{})
user := dbgen.User(t, db, database.User{})
job := dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{
Type: database.ProvisionerJobTypeWorkspaceBuild,
OrganizationID: org.ID,
})
templateVersion := dbgen.TemplateVersion(t, db, database.TemplateVersion{
JobID: job.ID,
OrganizationID: org.ID,
CreatedBy: user.ID,
})
err := provisionerdserver.InsertWorkspacePresetsAndParameters(
ctx,
logger,
db,
job.ID,
templateVersion.ID,
[]*sdkproto.Preset{{Name: "daily-driver"}, {Name: "daily-driver"}},
time.Now(),
)
require.ErrorContains(t, err, `duplicate preset name, must be unique per template: "daily-driver"`)
})
}
func TestInsertWorkspaceResource(t *testing.T) {