@@ -3243,12 +3243,17 @@ export async function updateWorkflowGroup(
32433243 // unchanged (workflow deleted, block removed). The result is applied against
32443244 // the fresh schema under the lock in phase 2.
32453245 const remapLeafTypeByColumn = new Map < string , ColumnDefinition [ 'type' ] > ( )
3246+ // The workflow id the leaf types above were resolved against. Phase 2 only
3247+ // applies the resolved types if the group still points at this workflow under
3248+ // the lock — a concurrent `workflowId` change would make them stale.
3249+ let resolvedForWorkflowId : string | undefined
32463250 if ( mappingUpdates . length > 0 ) {
32473251 try {
32483252 const preTable = await getTableById ( data . tableId )
32493253 const preGroup = preTable ?. schema . workflowGroups ?. find ( ( g ) => g . id === data . groupId )
32503254 const targetWorkflowId = data . workflowId ?? preGroup ?. workflowId
32513255 if ( targetWorkflowId ) {
3256+ resolvedForWorkflowId = targetWorkflowId
32523257 const [
32533258 { loadWorkflowFromNormalizedTables } ,
32543259 { flattenWorkflowOutputs } ,
@@ -3326,13 +3331,25 @@ export async function updateWorkflowGroup(
33263331 return { ...o , blockId : u . blockId , path : u . path }
33273332 } )
33283333
3329- const colByName = new Map ( schema . columns . map ( ( c ) => [ c . name , c ] ) )
3330- for ( const u of mappingUpdates ) {
3331- const newType = remapLeafTypeByColumn . get ( u . columnName )
3332- if ( ! newType ) continue
3333- const oldType = colByName . get ( u . columnName ) ?. type
3334- if ( newType !== oldType ) {
3335- remappedColumnTypes . set ( u . columnName , newType )
3334+ // Only apply the out-of-lock leaf-type resolution if the group still
3335+ // points at the workflow we resolved against. If a concurrent writer
3336+ // changed `workflowId` between phase 1 and now, those types are stale —
3337+ // leave column types unchanged (best-effort, same as a resolution
3338+ // failure) rather than stamping types from the old workflow.
3339+ const finalWorkflowId = data . workflowId ?? group . workflowId
3340+ if ( remapLeafTypeByColumn . size > 0 && resolvedForWorkflowId !== finalWorkflowId ) {
3341+ logger . warn (
3342+ `[${ requestId } ] Workflow group "${ data . groupId } " workflowId changed between leaf-type resolution and apply; leaving remapped column types unchanged.`
3343+ )
3344+ } else {
3345+ const colByName = new Map ( schema . columns . map ( ( c ) => [ c . name , c ] ) )
3346+ for ( const u of mappingUpdates ) {
3347+ const newType = remapLeafTypeByColumn . get ( u . columnName )
3348+ if ( ! newType ) continue
3349+ const oldType = colByName . get ( u . columnName ) ?. type
3350+ if ( newType !== oldType ) {
3351+ remappedColumnTypes . set ( u . columnName , newType )
3352+ }
33363353 }
33373354 }
33383355 }
0 commit comments