vxcontrol/pentagi · error
container not found
Error message
container not found
What it means
PutMsg writes terminal output for a container, but first validates containerID against the worker's in-memory set, refreshing it from GetFlowContainers on miss. This error means the given containerID is not among the flow's containers in the database — i.e. the terminal output references a container that does not exist or belongs to another flow. Note that a GetContainers DB failure is returned raw (error 208) instead.
Source
Thrown at backend/pkg/controller/termlog.go:63
msg string,
containerID int64,
taskID, subtaskID *int64,
) (int64, error) {
tlw.mx.Lock()
defer tlw.mx.Unlock()
if _, ok := tlw.containers[containerID]; !ok {
// try to update the container map
containers, err := tlw.GetContainers(ctx)
if err != nil {
return 0, err
}
tlw.containers = make(map[int64]struct{})
for _, container := range containers {
tlw.containers[container.ID] = struct{}{}
}
if _, ok := tlw.containers[containerID]; !ok {
return 0, fmt.Errorf("container not found")
}
}
termLog, err := tlw.db.CreateTermLog(ctx, database.CreateTermLogParams{
Type: msgType,
Text: database.SanitizeUTF8(msg),
ContainerID: containerID,
FlowID: tlw.flowID,
TaskID: database.Int64ToNullInt64(taskID),
SubtaskID: database.Int64ToNullInt64(subtaskID),
})
if err != nil {
return 0, fmt.Errorf("failed to create termlog: %w", err)
}
tlw.pub.TerminalLogAdded(ctx, termLog)
return termLog.ID, nilView on GitHub (pinned to ea665308ba)
Solutions
- Verify the containerID belongs to this flow (check the containers table by flow_id)
- Refresh/verify via GetContainers before writing; if the container is gone, drop or re-attach the terminal session
- Return 404/bad-request to callers that pass arbitrary container IDs
- Ensure container lifecycle code does not delete DB rows while exec output is still streaming
- For new containers, wait until the container row is committed before writing terminal logs
Example fix
// before
id, err := termWorker.PutMsg(ctx, db.TermlogTypeOutput, line, removedContainerID, nil, nil)
// after
containers, _ := termWorker.GetContainers(ctx)
if !containsContainer(containers, removedContainerID) {
log.Warn().Int64("container_id", removedContainerID).Msg("dropping output for removed container")
return 0, nil
}
id, err := termWorker.PutMsg(ctx, db.TermlogTypeOutput, line, removedContainerID, nil, nil) Defensive patterns
Strategy: validation
Validate before calling
func hasContainer(ctx context.Context, w controller.FlowTermLogWorker, containerID int64) bool {
cs, err := w.GetContainers(ctx)
if err != nil { return false }
for _, c := range cs { if c.ID == containerID { return true } }
return false
} Type guard
func isContainerNotFound(err error) bool {
return err != nil && strings.Contains(err.Error(), "container not found")
} Try / catch
id, err := w.PutMsg(ctx, msgType, line, containerID, taskID, subtaskID)
if isContainerNotFound(err) {
log.Warn().Int64("container_id", containerID).Msg("dropping terminal output for unknown container")
return 0, nil // or re-attach session to a valid container
}
if err != nil { return 0, err } Prevention
- Only pass container IDs obtained from GetContainers for this flow
- Stop terminal sessions before container removal/cleanup runs
- Validate containerID > 0 and comes from the flow's own exec session registry
- Re-check container liveness after long idle periods before writing
- Map this error to 404/bad-request at the API boundary
When it happens
Trigger: Calling PutMsg with a container ID from another flow, a container removed from Docker and deleted from the DB before output flushes, or a zero/uninitialized container ID.
Common situations: Exec sessions outliving their container's cleanup; passing container IDs captured before flow restart; race between container garbage collection and remaining buffered terminal lines.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/bf3bc1b2be226b5d.
Report an issue: GitHub.