vxcontrol/pentagi · error

failed to get search log: %w

Error message

failed to get search log: %w

What it means

GetLog wraps any error returned by the database query GetFlowSearchLog (fetching a search-log row by ID and flowID) into a contextual error. The library throws it whenever the underlying DB lookup fails, including the sql.ErrNoRows case where no matching log exists. It preserves the root cause via %w for errors.Is/As inspection.

Source

Thrown at backend/pkg/controller/slog.go:81

		TaskID:    database.Int64ToNullInt64(taskID),
		SubtaskID: database.Int64ToNullInt64(subtaskID),
	})
	if err != nil {
		return 0, fmt.Errorf("failed to create search log: %w", err)
	}

	slw.pub.SearchLogAdded(ctx, slLog)

	return slLog.ID, nil
}

func (slw *flowSearchLogWorker) GetLog(ctx context.Context, msgID int64) (database.Searchlog, error) {
	msg, err := slw.db.GetFlowSearchLog(ctx, database.GetFlowSearchLogParams{
		ID:     msgID,
		FlowID: slw.flowID,
	})
	if err != nil {
		return database.Searchlog{}, fmt.Errorf("failed to get search log: %w", err)
	}

	return msg, nil
}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Verify the msgID actually exists and belongs to the flow via a direct DB query on the search_logs table.
  2. Check errors.Is(err, database.ErrRecordNotFound) (or sql.ErrNoRows) in the caller and treat it as a 404, not a 500.
  3. Confirm the flowID used to create the worker matches the flow that produced the log entry.
  4. Check DB connectivity and migration state (goose migrations applied) if lookups fail across the board.

Example fix

// before
msg, err := slw.GetLog(ctx, msgID)
if err != nil {
    return fmt.Errorf("internal error: %v", err)
}
// after
msg, err := slw.GetLog(ctx, msgID)
if err != nil {
    if errors.Is(err, sql.ErrNoRows) {
        return ErrNotFound // surface as 404 to the client
    }
    return fmt.Errorf("get search log: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling GetLog, check the log exists and belongs to the flow
var exists bool
err := db.QueryRowContext(ctx,
    `SELECT EXISTS(SELECT 1 FROM search_logs WHERE id=$1 AND flow_id=$2)`,
    msgID, flowID).Scan(&exists)
if !exists { return ErrNotFound }

Type guard

func IsSearchLogNotFound(err error) bool {
    return errors.Is(err, sql.ErrNoRows)
}

Try / catch

msg, err := worker.GetLog(ctx, msgID)
if err != nil {
    if IsSearchLogNotFound(err) {
        http.Error(w, "search log not found", http.StatusNotFound)
        return
    }
    http.Error(w, "internal error", http.StatusInternalServerError)
    return
}

Prevention

When it happens

Trigger: Calling GetLog(ctx, msgID) on a flowSearchLogWorker when: the msgID does not exist in the search_logs table, the log exists but belongs to a different flow (flowID mismatch), or the database is unreachable/failing.

Common situations: Frontend requests a stale or deleted search log ID; worker cache is keyed by flowID but the caller passes an ID from another flow; transient Postgres connection drops or timeouts under load.

Related errors


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