@@ -1925,12 +1925,16 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
1925
1925
return xerrors .Errorf ("update workspace build deadline: %w" , err )
1926
1926
}
1927
1927
1928
+ appIDs := make ([]string , 0 )
1928
1929
agentTimeouts := make (map [time.Duration ]bool ) // A set of agent timeouts.
1929
1930
// This could be a bulk insert to improve performance.
1930
1931
for _ , protoResource := range jobType .WorkspaceBuild .Resources {
1931
1932
for _ , protoAgent := range protoResource .Agents {
1932
1933
dur := time .Duration (protoAgent .GetConnectionTimeoutSeconds ()) * time .Second
1933
1934
agentTimeouts [dur ] = true
1935
+ for _ , app := range protoAgent .GetApps () {
1936
+ appIDs = append (appIDs , app .GetId ())
1937
+ }
1934
1938
}
1935
1939
1936
1940
err = InsertWorkspaceResource (ctx , db , job .ID , workspaceBuild .Transition , protoResource , telemetrySnapshot )
@@ -1946,10 +1950,15 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
1946
1950
1947
1951
var sidebarAppID uuid.NullUUID
1948
1952
hasAITask := len (jobType .WorkspaceBuild .AiTasks ) == 1
1953
+ warnUnknownSidebarAppID := false
1949
1954
if hasAITask {
1950
1955
task := jobType .WorkspaceBuild .AiTasks [0 ]
1951
- if task .SidebarApp == nil {
1952
- return xerrors .Errorf ("update ai task: sidebar app is nil" )
1956
+ if task .SidebarApp == nil || len (task .SidebarApp .Id ) == 0 {
1957
+ return xerrors .Errorf ("update ai task: sidebar app is nil or empty" )
1958
+ }
1959
+
1960
+ if ! slices .Contains (appIDs , task .SidebarApp .Id ) {
1961
+ warnUnknownSidebarAppID = true
1953
1962
}
1954
1963
1955
1964
id , err := uuid .Parse (task .SidebarApp .Id )
@@ -1960,18 +1969,53 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
1960
1969
sidebarAppID = uuid.NullUUID {UUID : id , Valid : true }
1961
1970
}
1962
1971
1972
+ if warnUnknownSidebarAppID {
1973
+ // Ref: https://github.com/coder/coder/issues/18776
1974
+ // This can happen for a number of reasons:
1975
+ // 1. Misconfigured template
1976
+ // 2. Count=0 on the agent due to stop transition, meaning the associated coder_app was not inserted.
1977
+ // Failing the build at this point is not ideal, so log a warning instead.
1978
+ s .Logger .Warn (ctx , "unknown ai_task_sidebar_app_id" ,
1979
+ slog .F ("ai_task_sidebar_app_id" , sidebarAppID .UUID .String ()),
1980
+ slog .F ("job_id" , job .ID .String ()),
1981
+ slog .F ("workspace_id" , workspace .ID ),
1982
+ slog .F ("workspace_build_id" , workspaceBuild .ID ),
1983
+ slog .F ("transition" , string (workspaceBuild .Transition )),
1984
+ )
1985
+ // In order to surface this to the user, we will also insert a warning into the build logs.
1986
+ if _ , err := db .InsertProvisionerJobLogs (ctx , database.InsertProvisionerJobLogsParams {
1987
+ JobID : jobID ,
1988
+ CreatedAt : []time.Time {now },
1989
+ Source : []database.LogSource {database .LogSourceProvisionerDaemon },
1990
+ Level : []database.LogLevel {database .LogLevelWarn },
1991
+ Stage : []string {"Cleaning Up" },
1992
+ Output : []string {
1993
+ fmt .Sprintf ("Unknown ai_task_sidebar_app_id %q. This workspace will be unable to run AI tasks. This may be due to a template configuration issue, please check with the template author." , sidebarAppID .UUID .String ()),
1994
+ },
1995
+ }); err != nil {
1996
+ s .Logger .Error (ctx , "insert provisioner job log for ai task sidebar app id warning" ,
1997
+ slog .F ("job_id" , jobID ),
1998
+ slog .F ("workspace_id" , workspace .ID ),
1999
+ slog .F ("workspace_build_id" , workspaceBuild .ID ),
2000
+ slog .F ("transition" , string (workspaceBuild .Transition )),
2001
+ )
2002
+ }
2003
+ // Important: reset hasAITask and sidebarAppID so that we don't run into a fk constraint violation.
2004
+ hasAITask = false
2005
+ sidebarAppID = uuid.NullUUID {}
2006
+ }
2007
+
1963
2008
// Regardless of whether there is an AI task or not, update the field to indicate one way or the other since it
1964
2009
// always defaults to nil. ONLY if has_ai_task=true MUST ai_task_sidebar_app_id be set.
1965
- err = db .UpdateWorkspaceBuildAITaskByID (ctx , database.UpdateWorkspaceBuildAITaskByIDParams {
2010
+ if err : = db .UpdateWorkspaceBuildAITaskByID (ctx , database.UpdateWorkspaceBuildAITaskByIDParams {
1966
2011
ID : workspaceBuild .ID ,
1967
2012
HasAITask : sql.NullBool {
1968
2013
Bool : hasAITask ,
1969
2014
Valid : true ,
1970
2015
},
1971
2016
SidebarAppID : sidebarAppID ,
1972
2017
UpdatedAt : now ,
1973
- })
1974
- if err != nil {
2018
+ }); err != nil {
1975
2019
return xerrors .Errorf ("update workspace build ai tasks flag: %w" , err )
1976
2020
}
1977
2021
0 commit comments