fix(tools): rebuild the flow primary container when the daemon lost it

A flow stores the id of its primary container in the database. When that
container is removed outside pentagi the row keeps status 'running', so
Prepare reused a container the daemon no longer knows about and every
terminal call failed with "No such container" until the flow was recreated.

Confirm with the daemon before reusing the stored container and let the
existing remove-and-rebuild path take over when it is gone. An unreachable
daemon is still an error, so a transient failure cannot discard a healthy
container.
This commit is contained in:
Fahad
2026-08-03 22:58:38 +03:00
parent 16f1e0c42e
commit 7d675b313a

View File

@@ -481,18 +481,24 @@ func (fte *flowToolsExecutor) SetGraphitiClient(client *graphiti.Client) {
func (fte *flowToolsExecutor) Prepare(ctx context.Context) error {
if cnt, err := fte.db.GetFlowPrimaryContainer(ctx, fte.flowID); err == nil {
switch cnt.Status {
case database.ContainerStatusRunning:
fte.primaryID = cnt.ID
fte.primaryLID = cnt.LocalID.String
if err := fte.syncMissingFiles(ctx); err != nil {
containerName := PrimaryTerminalName(fte.cfg.TenantPrefix(), fte.flowID)
return fmt.Errorf("failed to sync missing files to container '%s': %w", containerName, err)
// the stored status goes stale when the container is removed outside pentagi
if cnt.Status == database.ContainerStatusRunning {
containerName := PrimaryTerminalName(fte.cfg.TenantPrefix(), fte.flowID)
running, err := fte.docker.IsContainerRunning(ctx, cnt.LocalID.String)
if err != nil {
return fmt.Errorf("failed to inspect container '%s': %w", containerName, err)
}
if running {
fte.primaryID = cnt.ID
fte.primaryLID = cnt.LocalID.String
if err := fte.syncMissingFiles(ctx); err != nil {
return fmt.Errorf("failed to sync missing files to container '%s': %w", containerName, err)
}
return nil
}
return nil
default:
fte.docker.RemoveContainer(ctx, cnt.LocalID.String, cnt.ID)
}
fte.docker.RemoveContainer(ctx, cnt.LocalID.String, cnt.ID)
}
// Explicit capability allow-list (CapDrop: ALL below): Docker's default 14