vxcontrol/pentagi · error
failed to put terminal log (stdout)
Error message
failed to put terminal log (stdout): %w
What it means
After a successful exec, getExecResult logs the styled output to the terminal log store via t.tlp.PutMsg with TermlogTypeStdout. This error wraps a failure of that persistence call, meaning the command ran fine but its transcript could not be recorded, so the function aborts to keep the terminal log consistent.
Solutions
- Check database connectivity and logs (Postgres health, connection pool settings)
- Verify the termlog table constraints/column sizes vs the output size (truncate large outputs before PutMsg)
- Sanitize non-UTF8 output before logging
- Retry the operation once the DB recovers — the command result itself was valid
Example fix
// before
_, err = t.tlp.PutMsg(ctx, database.TermlogTypeStdout, styledOutput, ...)
if err != nil { return "", fmt.Errorf("failed to put terminal log (stdout): %w", err) }
// after
styledOutput = truncateString(strings.ToValidUTF8(styledOutput, string(utf8.RuneError)), 10000)
_, err = t.tlp.PutMsg(ctx, database.TermlogTypeStdout, styledOutput, ...) Defensive patterns
Strategy: fallback
Validate before calling
// pre-flight DB check in deployment health routine
if err := db.PingContext(ctx); err != nil {
log.Warn("database unreachable; termlog writes will fail")
} Try / catch
out, err := term.ExecCommand(ctx, flowID, cmd, false)
if err != nil && strings.Contains(err.Error(), "failed to put terminal log") {
// command succeeded; only logging failed — treat output as usable with degraded audit
log.Warn("termlog stdout write failed", "err", err)
} Prevention
- Monitor PostgreSQL connectivity and pool saturation
- Cap/truncate command output before it reaches the termlog store
- Sanitize binary/non-UTF8 output
- Alert on termlog write failures to keep audit logs trustworthy
When it happens
Trigger: PutMsg(ctx, database.TermlogTypeStdout, styledOutput, ...) returns an error — typically the database write fails: DB connection lost, transaction/lock issues, or the storage layer rejects the (possibly large or invalid-UTF8) output payload.
Common situations: PostgreSQL outage or connection-pool exhaustion during heavy pentest activity; output exceeding a size limit in the termlog table; encoding issues in binary command output.
Related errors
- failed to put terminal log (read file cmd)
- failed to put terminal log (read file content)
- failed to put terminal log (stdin)
- failed to put terminal log (write file cmd)
- failed to check flow status
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/d432920345cfbc04.
Report an issue: GitHub.
Appendix: source
Thrown at backend/pkg/tools/terminal.go:319
"For long batch commands, wrap with shell timeout utility: 'timeout %d <command>' to ensure clean completion",
ctx.Err(),
truncateString(dst.String(), 500),
suggestedTimeout,
)
}
// wait for the exec process to finish
_, err = t.dockerClient.ContainerExecInspect(ctx, id)
if err != nil {
return "", fmt.Errorf("failed to inspect exec process: %w", err)
}
results := dst.String()
// Style system output with color coding
styledOutput := fmt.Sprintf("%s%s%s%s", ansiColorSystemMsg, results, ansiColorReset, ansiLineTerminator)
_, err = t.tlp.PutMsg(ctx, database.TermlogTypeStdout, styledOutput, t.containerID, t.taskID, t.subtaskID)
if err != nil {
return "", fmt.Errorf("failed to put terminal log (stdout): %w", err)
}
if results == "" {
results = "Command completed successfully with exit code 0. No output produced (silent success)"
}
return results, nil
}
func (t *terminal) ReadFile(ctx context.Context, flowID int64, path string) (string, error) {
if path == "" {
return "", fmt.Errorf("path is required and cannot be empty")
}
cwd := docker.WorkFolderPathInContainer
escapedPath := strings.ReplaceAll(path, "'", "'\"'\"'")
catCommand := fmt.Sprintf("cat '%s'", escapedPath)
// Format read file command with stylingView on GitHub (pinned to ea665308ba)