vxcontrol/pentagi · error

failed to put terminal log (read file content): %w

Error message

failed to put terminal log (read file content): %w

What it means

After successfully reading the file contents via readFileFromContainer, ReadFile records the styled content into the terminal transcript with PutMsg (TermlogTypeStdout). This error wraps a failure of that final logging write; the file was read, but the transcript could not be updated, so the read is reported as failed to preserve log integrity.

Source

Thrown at backend/pkg/tools/terminal.go:353

	escapedPath := strings.ReplaceAll(path, "'", "'\"'\"'")
	catCommand := fmt.Sprintf("cat '%s'", escapedPath)
	// Format read file command with styling
	styledCommand := fmt.Sprintf("%s $ %s%s%s%s", cwd, ansiColorInputCmd, catCommand, ansiColorReset, ansiLineTerminator)
	_, err := t.tlp.PutMsg(ctx, database.TermlogTypeStdin, styledCommand, t.containerID, t.taskID, t.subtaskID)
	if err != nil {
		return "", fmt.Errorf("failed to put terminal log (read file cmd): %w", err)
	}

	content, err := t.readFileFromContainer(ctx, flowID, path)
	if err != nil {
		return "", err
	}

	// Style file content output
	styledContent := fmt.Sprintf("%s%s%s%s", ansiColorSystemMsg, content, ansiColorReset, ansiLineTerminator)
	_, err = t.tlp.PutMsg(ctx, database.TermlogTypeStdout, styledContent, t.containerID, t.taskID, t.subtaskID)
	if err != nil {
		return "", fmt.Errorf("failed to put terminal log (read file content): %w", err)
	}

	return content, nil
}

// readFileFromContainer copies path out of the flow's container and returns
// its content. It performs no terminal-log writes, so callers that need the
// content only as an intermediate step (e.g. EditFile, before reapplying a
// diff and writing back) don't echo a spurious "cat" transcript entry.
func (t *terminal) readFileFromContainer(ctx context.Context, flowID int64, path string) (string, error) {
	containerName := PrimaryTerminalName(t.tenantPrefix, flowID)

	isRunning, err := t.dockerClient.IsContainerRunning(ctx, t.containerLID)
	if err != nil {
		return "", fmt.Errorf("runtime verification failed: %w", err)
	}
	if !isRunning {
		return "", fmt.Errorf("container runtime is not operational")

View on GitHub (pinned to ea665308ba)

Solutions

  1. Check database connectivity and health first
  2. Truncate or size-limit content before PutMsg for large files
  3. Sanitize non-UTF8 content before logging
  4. Retry after the DB recovers; the content itself was read successfully

Example fix

// before
_, err = t.tlp.PutMsg(ctx, database.TermlogTypeStdout, styledContent, ...)
// after
styledContent = truncateString(strings.ToValidUTF8(styledContent, "?"), 50000)
_, err = t.tlp.PutMsg(ctx, database.TermlogTypeStdout, styledContent, ...)
Defensive patterns

Strategy: fallback

Validate before calling

info, err := os.Stat(localPathOrKnownSize)
if err == nil && info.Size() > maxLoggableBytes {
    return errors.New("file too large to log; read via direct copy instead")
}

Try / catch

content, err := term.ReadFile(ctx, flowID, path)
if err != nil && strings.Contains(err.Error(), "failed to put terminal log (read file content)") {
    // content was read; failure was persistence — retry or log-and-continue
    log.Warn("stdout termlog write failed for file content", "err", err)
}

Prevention

When it happens

Trigger: PutMsg(ctx, database.TermlogTypeStdout, styledContent, ...) fails when persisting the file content — DB connection failure, oversized payload (large file content), or encoding constraints in the termlog table.

Common situations: Reading very large files whose content exceeds storage limits; PostgreSQL outage or pool exhaustion; binary files producing invalid UTF-8 content.

Related errors


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