Common issues and solutions for the Task Engine.
Problem: Action output referenced before action executes.
// ❌ Wrong - action doesn't exist yet
engine.ActionOutput("read-file", "content")
// ✅ Correct - reference existing action
engine.ActionOutput("read-source", "content")Solution: Ensure action IDs match exactly and actions execute before being referenced.
Problem: Referenced output key doesn't exist in action output.
// ❌ Wrong - key doesn't exist
engine.ActionOutput("read-file", "nonexistent")
// ✅ Correct - use existing key or omit for entire output
engine.ActionOutput("read-file", "content")
engine.ActionOutput("read-file", "") // entire outputSolution: Check action output structure or omit key for entire output.
Problem: Task halts when any action fails.
// ❌ Task stops here
action1.Execute(ctx) // fails
action2.Execute(ctx) // never runs
// ✅ Handle errors gracefully
if err := action1.Execute(ctx); err != nil {
if errors.Is(err, engine.ErrPrerequisiteNotMet) {
// Skip task gracefully
return nil
}
return err
}Solution: Use ErrPrerequisiteNotMet for graceful task abortion.
Problem: Task doesn't respect context cancellation.
// ✅ Always check context in long-running actions
func (a *MyAction) Execute(ctx context.Context) error {
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
// Do work
}
}
}Solution: Check ctx.Done() in long-running operations.
Problem: Container name/ID doesn't exist.
// ❌ Container might not exist
docker.NewGetContainerStateAction(logger, "my-container")
// ✅ Check if container exists first
containers := docker.NewGetAllContainersStateAction(logger)
// Filter by name/IDSolution: Use GetAllContainersStateAction to verify container existence.
Problem: Docker commands fail due to permissions.
// ❌ Might fail without proper permissions
docker.NewDockerRunAction(logger, "nginx", nil, nil, nil)
// ✅ Ensure user is in docker group
// Run: sudo usermod -aG docker $USERSolution: Add user to docker group or use sudo.
Problem: File/directory doesn't exist.
// ❌ Path might not exist
file.NewReadFileAction("/nonexistent/file", &content, logger)
// ✅ Create directories first
file.NewCreateDirectoriesAction(logger).WithParameters(
engine.StaticParameter{Value: "/path/to"},
engine.StaticParameter{Value: []string{"parent", "child"}},
)Solution: Create parent directories before file operations.
Problem: Insufficient file permissions.
// ❌ Might fail without proper permissions
file.NewWriteFileAction("/etc/config", content, true, nil, logger)
// ✅ Check permissions or use appropriate paths
file.NewWriteFileAction("/tmp/config", content, true, nil, logger)Solution: Use appropriate paths or check file permissions.
Problem: Systemd service doesn't exist.
// ❌ Service might not exist
system.NewGetServiceStatusAction(logger, "nonexistent-service")
// ✅ Check service existence first
// Use systemctl list-units --type=serviceSolution: Verify service name with systemctl list-units.
Problem: Insufficient privileges for service control.
// ❌ Might fail without sudo
system.NewManageServiceAction(logger).WithParameters(
engine.StaticParameter{Value: "nginx"},
engine.StaticParameter{Value: "restart"},
)
// ✅ Ensure proper privileges or use sudoSolution: Run with appropriate privileges or use sudo.
// ✅ Proper error handling
if err := task.Run(ctx); err != nil {
if errors.Is(err, engine.ErrPrerequisiteNotMet) {
logger.Warn("Prerequisites not met", "error", err)
return nil
}
logger.Error("Task failed", "error", err)
return err
}// ✅ Validate parameters before use
if actionID == "" {
return fmt.Errorf("action ID cannot be empty")
}// ✅ Always pass context through
func (a *MyAction) Execute(ctx context.Context) error {
// Use ctx for cancellation, timeouts, etc.
return nil
}logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))// Print all action outputs
for id, output := range globalContext.ActionOutputs {
logger.Debug("Action output", "id", id, "output", output)
}// Check task execution state
logger.Info("Task state",
"completed", task.GetCompletedTasks(),
"totalTime", task.GetTotalTime(),
)