diff --git a/go/src/infra/cros/cmd/paris/internal/tasks/local_recovery.go b/go/src/infra/cros/cmd/paris/internal/tasks/local_recovery.go
index 2ddcf18..25ec7fc 100644
--- a/go/src/infra/cros/cmd/paris/internal/tasks/local_recovery.go
+++ b/go/src/infra/cros/cmd/paris/internal/tasks/local_recovery.go
@@ -12,6 +12,7 @@
"path/filepath"
"strings"
"sync/atomic"
+ "time"
"github.com/maruel/subcommands"
@@ -285,7 +286,7 @@
}
}
ctx = scopes.WithParams(ctx, params)
- access, err := recovery.NewLocalTLWAccess(ctx, ic)
+ access, err := newLocalTLWAccessWithTimeout(ctx, ic)
if err != nil {
return errors.Fmt("local recovery: create tlw access: %w", err)
}
@@ -318,6 +319,14 @@
return nil
}
+// newLocalTLWAccessWithTimeout initializes local TLW access with a 10-second timeout
+// to prevent CLI executions from hanging indefinitely if the lab gRPC service or proxy is unreachable.
+func newLocalTLWAccessWithTimeout(ctx context.Context, ic *recovery.LocalTLWConfig) (tlw.Access, error) {
+ initCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
+ defer cancel()
+ return recovery.NewLocalTLWAccess(initCtx, ic)
+}
+
func (c *localRecoveryRun) getLogRoot() (string, error) {
// TODO(gregorynisbet): Clean up the logs, include the current timestamp, or generally
// do something smarter than just setting the logs to "./logs".