vxcontrol/pentagi · error

failed to get container %d: %w

Error message

failed to get container %d: %w

What it means

After handler validation, GetAssistantExecutor fetches the flow's primary container via fte.db.GetFlowPrimaryContainer. This error wraps any database failure (connection error, no row, query error) while resolving that container, and is needed because terminal/exec tools are bound to the container ID.

Source

Thrown at backend/pkg/tools/tools.go:843

	if cfg.Installer == nil {
		return nil, fmt.Errorf("installer handler is required")
	}

	if cfg.Memorist == nil {
		return nil, fmt.Errorf("memorist handler is required")
	}

	if cfg.Pentester == nil {
		return nil, fmt.Errorf("pentester handler is required")
	}

	if cfg.Searcher == nil {
		return nil, fmt.Errorf("searcher handler is required")
	}

	container, err := fte.db.GetFlowPrimaryContainer(context.Background(), fte.flowID)
	if err != nil {
		return nil, fmt.Errorf("failed to get container %d: %w", fte.flowID, err)
	}

	term := NewTerminalTool(
		fte.flowID, nil, nil,
		container.ID,
		container.LocalID.String,
		fte.cfg.TenantPrefix(),
		fte.docker,
		fte.tlp,
		time.Duration(fte.cfg.TerminalToolTimeout)*time.Second,
	)

	definitions := []llms.FunctionDefinition{
		registryDefinitions[TerminalToolName],
		registryDefinitions[FileToolName],
	}
	handlers := map[string]ExecutorHandler{
		TerminalToolName: term.Handle,

View on GitHub (pinned to ea665308ba)

Solutions

  1. Inspect the wrapped cause (%w) to distinguish 'no rows' from a DB connectivity error.
  2. If no rows: ensure the flow's primary container was created and recorded (start the flow / re-run container provisioning).
  3. If connectivity: verify PostgreSQL is up, credentials and DATABASE_URL are correct, and the pool is not exhausted.
  4. Confirm the flow ID passed to flowToolsExecutor matches an existing flow.

Example fix

// before
container, err := fte.db.GetFlowPrimaryContainer(ctx, fte.flowID)
if err != nil { return nil, fmt.Errorf("failed to get container %d: %w", fte.flowID, err) }
// after — handle 'not found' distinctly upstream
cfg.ContainerID = container.ID // ensure flow provisioning ran:
// 1) create flow  2) start primary container  3) then call GetAssistantExecutor
Defensive patterns

Strategy: try-catch

Validate before calling

var count int64
db.Model(&models.Flow{}).Where("id = ?", flowID).Count(&count)
if count == 0 {
    return errors.New("flow does not exist")
}
// optionally: check a primary container row exists before calling GetAssistantExecutor

Try / catch

executor, err := fte.GetAssistantExecutor(cfg)
if err != nil {
    var noRows sql.ErrNoRows
    if errors.As(err, &noRows) || strings.Contains(err.Error(), "failed to get container") {
        // check DB connectivity and that the flow's primary container was provisioned
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetAssistantExecutor when the flow has no primary container row in the database, or the DB is unreachable/failing — the sqlc/GORM error from GetFlowPrimaryContainer is wrapped with flow ID %d.

Common situations: Flow created but its Docker container never registered in the DB; container record deleted while the flow still exists; PostgreSQL down or connection pool exhausted; using a flow ID that was never started.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/c4de2bf030669ff8. Report an issue: GitHub.