vxcontrol/pentagi · error

failed to create screenshot: %w

Error message

failed to create screenshot: %w

What it means

PutScreenshot persists a screenshot record via the database (CreateScreenshot) with sanitized URL and flow/task/subtask IDs; on DB failure it returns "failed to create screenshot: %w". The controller only publishes the ScreenshotAdded event after the insert succeeds, so this error means nothing was stored or broadcast.

Source

Thrown at backend/pkg/controller/screenshot.go:47

		flowID:     flowID,
		containers: make(map[int64]struct{}),
		pub:        pub,
	}
}

func (sw *flowScreenshotWorker) PutScreenshot(ctx context.Context, name, url string, taskID, subtaskID *int64) (int64, error) {
	sw.mx.Lock()
	defer sw.mx.Unlock()

	screenshot, err := sw.db.CreateScreenshot(ctx, database.CreateScreenshotParams{
		Name:      database.SanitizeUTF8(name),
		Url:       database.SanitizeUTF8(url),
		FlowID:    sw.flowID,
		TaskID:    database.Int64ToNullInt64(taskID),
		SubtaskID: database.Int64ToNullInt64(subtaskID),
	})
	if err != nil {
		return 0, fmt.Errorf("failed to create screenshot: %w", err)
	}

	sw.pub.ScreenshotAdded(ctx, screenshot)

	return screenshot.ID, nil
}

func (sw *flowScreenshotWorker) GetScreenshot(ctx context.Context, screenshotID int64) (database.Screenshot, error) {
	screenshot, err := sw.db.GetScreenshot(ctx, screenshotID)
	if err != nil {
		return database.Screenshot{}, fmt.Errorf("failed to get screenshot: %w", err)
	}

	return screenshot, nil
}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Unwrap the error to see the driver/constraint failure.
  2. Check screenshot payload size against the DB column type and Postgres limits.
  3. Verify DB connectivity and that the parent flow/task rows still exist (FK constraints).
  4. Retry the put after transient DB failures — the insert is atomic and leaves no partial state.

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

// validate payload size and parent existence before inserting
if len(screenshotData) > maxScreenshotBytes {
    return fmt.Errorf("screenshot too large: %d bytes", len(screenshotData))
}
if _, err := db.GetFlow(ctx, flowID); err != nil {
    return err // parent row missing would violate FK
}

Type guard

null

Try / catch

id, err := sw.PutScreenshot(ctx, taskID, subtaskID, url, data)
if err != nil {
    if strings.Contains(err.Error(), "failed to create screenshot") {
        logger.WithError(err).Warn("screenshot not persisted")
        // degrade gracefully: agent continues without the screenshot record
        return 0, nil
    }
    return 0, err
}

Prevention

When it happens

Trigger: An agent/tool calls the screenshot worker's PutScreenshot while the INSERT fails: DB unreachable, NOT NULL/FK violation on flow_id/task_id, oversized data column exceeding limits, or context cancellation mid-insert.

Common situations: Screenshot blob exceeding column size limits (e.g. large base64 payloads vs. TEXT/bytea constraints); database restarted mid-run; worker outliving a cancelled context; foreign key mismatch when the parent task was deleted concurrently.

Related errors


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