vxcontrol/pentagi · error
failed to create termlog: %w
Error message
failed to create termlog: %w
What it means
PutMsg inserts the terminal log row via db.CreateTermLog after the container check passes. This error wraps the underlying database failure: FK violation (e.g. task/subtask rows deleted concurrently), connection loss, context cancellation, or oversized/invalid text data (text is UTF-8-sanitized first, so encoding is usually not the cause).
Source
Thrown at backend/pkg/controller/termlog.go:76
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, nil
}
func (tlw *flowTermLogWorker) GetMsg(ctx context.Context, msgID int64) (database.Termlog, error) {
msg, err := tlw.db.GetTermLog(ctx, msgID)
if err != nil {
return database.Termlog{}, fmt.Errorf("failed to get termlog: %w", err)
}
return msg, nil
}
func (tlw *flowTermLogWorker) GetContainers(ctx context.Context) ([]database.Container, error) {
containers, err := tlw.db.GetFlowContainers(ctx, tlw.flowID)View on GitHub (pinned to ea665308ba)
Solutions
- Inspect the wrapped cause to distinguish FK vs connection vs cancellation
- Validate taskID/subtaskID still exist and belong to the flow before logging
- Add bounded retry with backoff for transient driver errors on terminal writes
- Keep ctx alive for log writes (background context) so request cancellation doesn't drop terminal history
- Check DB logs for the failing constraint and fix the caller's ID lifecycle
Example fix
// before
if _, err := termWorker.PutMsg(ctx, t, line, cid, &taskID, &subtaskID); err != nil { return err }
// after
if _, err := termWorker.PutMsg(context.WithoutCancel(ctx), t, line, cid, &taskID, &subtaskID); err != nil {
if isTransient(err) { return retryPutMsg(t, line, cid, taskID, subtaskID) }
return err
} Defensive patterns
Strategy: retry
Validate before calling
func canWriteTermLog(ctx context.Context, q database.Querier, flowID int64, taskID, subtaskID *int64) error {
if ctx.Err() != nil { return ctx.Err() }
if taskID != nil {
if _, err := q.GetFlowTask(ctx, flowID, *taskID); err != nil { return err }
}
if subtaskID != nil {
if _, err := q.GetSubtask(ctx, *subtaskID); err != nil { return err }
}
return nil
} Type guard
func isForeignKeyErr(err error) bool {
var pgErr *pgconn.PgError
return errors.As(err, &pgErr) && pgErr.Code == "23503"
} Try / catch
err := retry(3, backoff, func() error {
_, err := w.PutMsg(ctx, msgType, line, containerID, taskID, subtaskID)
if isForeignKeyErr(err) || errors.Is(err, context.Canceled) { return stop(err) }
return err // transient errors are retried
}) Prevention
- Use context.WithoutCancel for terminal history writes so request teardown doesn't drop logs
- Retry only transient DB errors (driver.ErrBadConn, connection reset); never retry FK violations
- Ensure subtask cleanup waits for pending terminal writes
- Cap message size and flush in batches to avoid timeouts under output bursts
- Monitor Postgres availability; alert on restarts during active flows
When it happens
Trigger: DB connection dropped during heavy terminal output; taskID/subtaskID pointing at rows deleted mid-execution; canceled context from a request timeout; violating a NOT NULL/length constraint on text.
Common situations: Long-running exec sessions surviving a Postgres restart; agents racing subtask completion/cleanup while still emitting output; very large paste/burst writes hitting timeouts.
Related errors
- failed to create tool call log: %w
- failed to update tool call log result: %w
- failed to update tool call log failed result: %w
- failed to get containers: %w
- knowledge: list user docs: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/f76cb35762182903.
Report an issue: GitHub.