Browse Source

refactor(misc): replace fmt.Errorf with errors.New where possible

No need to to invoke the whole Printf machinery for constant strings. While
this shouldn't have an impact on memory consumption nor allocation (as
constructing errors to return is never in a hot path), this should reduce a bit
the code size, as errors.New will be inlined to a simple struct initialization
instead of a function call.
jvoisin 6 months ago
parent
commit
dd44fbcc76
37 changed files with 88 additions and 60 deletions
  1. 1 1
      client/client.go
  2. 2 1
      internal/cli/reset_password.go
  3. 3 2
      internal/config/parser.go
  4. 4 3
      internal/config/validators.go
  5. 4 5
      internal/googlereader/handler.go
  6. 2 1
      internal/googlereader/item.go
  7. 2 2
      internal/googlereader/request_modifier.go
  8. 2 1
      internal/integration/apprise/apprise.go
  9. 2 1
      internal/integration/espial/espial.go
  10. 2 1
      internal/integration/instapaper/instapaper.go
  11. 2 1
      internal/integration/linkace/linkace.go
  12. 2 1
      internal/integration/linkding/linkding.go
  13. 2 1
      internal/integration/linktaco/linktaco.go
  14. 2 1
      internal/integration/linkwarden/linkwarden.go
  15. 2 1
      internal/integration/notion/notion.go
  16. 2 1
      internal/integration/nunuxkeeper/nunuxkeeper.go
  17. 2 2
      internal/integration/pinboard/pinboard.go
  18. 2 1
      internal/integration/pushover/pushover.go
  19. 2 1
      internal/integration/raindrop/raindrop.go
  20. 2 1
      internal/integration/readeck/readeck.go
  21. 2 1
      internal/integration/readwise/readwise.go
  22. 2 1
      internal/integration/shaarli/shaarli.go
  23. 2 1
      internal/integration/shiori/shiori.go
  24. 2 1
      internal/integration/wallabag/wallabag.go
  25. 2 1
      internal/integration/webhook/webhook.go
  26. 3 2
      internal/reader/processor/bilibili.go
  27. 2 1
      internal/reader/readability/readability_test.go
  28. 3 3
      internal/reader/sanitizer/srcset.go
  29. 2 2
      internal/reader/urlcleaner/urlcleaner.go
  30. 2 1
      internal/storage/api_key.go
  31. 3 2
      internal/storage/user_session.go
  32. 2 1
      internal/systemd/systemd.go
  33. 3 2
      internal/template/functions.go
  34. 3 2
      internal/urllib/url.go
  35. 2 2
      internal/validator/enclosure.go
  36. 5 4
      internal/validator/entry.go
  37. 4 4
      internal/validator/validator.go

+ 1 - 1
client/client.go

@@ -125,7 +125,7 @@ func (c *Client) UserByID(userID int64) (*User, error) {
 
 // UserByUsername returns a single user.
 func (c *Client) UserByUsername(username string) (*User, error) {
-	body, err := c.request.Get(fmt.Sprintf("/v1/users/%s", username))
+	body, err := c.request.Get("/v1/users/" + username)
 	if err != nil {
 		return nil, err
 	}

+ 2 - 1
internal/cli/reset_password.go

@@ -4,6 +4,7 @@
 package cli // import "miniflux.app/v2/internal/cli"
 
 import (
+	"errors"
 	"fmt"
 
 	"miniflux.app/v2/internal/model"
@@ -19,7 +20,7 @@ func resetPassword(store *storage.Storage) {
 	}
 
 	if user == nil {
-		printErrorAndExit(fmt.Errorf("user not found"))
+		printErrorAndExit(errors.New("user not found"))
 	}
 
 	userModificationRequest := &model.UserModificationRequest{

+ 3 - 2
internal/config/parser.go

@@ -7,6 +7,7 @@ import (
 	"bufio"
 	"bytes"
 	"crypto/rand"
+	"errors"
 	"fmt"
 	"io"
 	"net/url"
@@ -60,7 +61,7 @@ func (cp *configParser) postParsing() error {
 
 	scheme := strings.ToLower(parsedURL.Scheme)
 	if scheme != "https" && scheme != "http" {
-		return fmt.Errorf("BASE_URL scheme must be http or https")
+		return errors.New("BASE_URL scheme must be http or https")
 	}
 
 	cp.options.options["BASE_URL"].ParsedStringValue = baseURL
@@ -294,7 +295,7 @@ func readSecretFileValue(filename string) (string, error) {
 
 	value := string(bytes.TrimSpace(data))
 	if value == "" {
-		return "", fmt.Errorf("secret file is empty")
+		return "", errors.New("secret file is empty")
 	}
 
 	return value, nil

+ 4 - 3
internal/config/validators.go

@@ -4,6 +4,7 @@
 package config // import "miniflux.app/v2/internal/config"
 
 import (
+	"errors"
 	"fmt"
 	"slices"
 	"strconv"
@@ -29,7 +30,7 @@ func validateListChoices(inputValues, choices []string) error {
 func validateGreaterThan(rawValue string, min int) error {
 	intValue, err := strconv.Atoi(rawValue)
 	if err != nil {
-		return fmt.Errorf("value must be an integer")
+		return errors.New("value must be an integer")
 	}
 	if intValue > min {
 		return nil
@@ -40,7 +41,7 @@ func validateGreaterThan(rawValue string, min int) error {
 func validateGreaterOrEqualThan(rawValue string, min int) error {
 	intValue, err := strconv.Atoi(rawValue)
 	if err != nil {
-		return fmt.Errorf("value must be an integer")
+		return errors.New("value must be an integer")
 	}
 	if intValue >= min {
 		return nil
@@ -51,7 +52,7 @@ func validateGreaterOrEqualThan(rawValue string, min int) error {
 func validateRange(rawValue string, min, max int) error {
 	intValue, err := strconv.Atoi(rawValue)
 	if err != nil {
-		return fmt.Errorf("value must be an integer")
+		return errors.New("value must be an integer")
 	}
 	if intValue < min || intValue > max {
 		return fmt.Errorf("value must be between %d and %d", min, max)

+ 4 - 5
internal/googlereader/handler.go

@@ -126,8 +126,7 @@ func checkOutputFormat(r *http.Request) error {
 		output = request.QueryStringParam(r, "output", "")
 	}
 	if output != "json" {
-		err := fmt.Errorf("googlereader: only json output is supported")
-		return err
+		return errors.New("googlereader: only json output is supported")
 	}
 	return nil
 }
@@ -280,7 +279,7 @@ func (h *handler) editTagHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	if len(addTags) == 0 && len(removeTags) == 0 {
-		err = fmt.Errorf("googlreader: add or/and remove tags should be supplied")
+		err = errors.New("googlreader: add or/and remove tags should be supplied")
 		json.ServerError(w, r, err)
 		return
 	}
@@ -1014,7 +1013,7 @@ func (h *handler) userInfoHandler(w http.ResponseWriter, r *http.Request) {
 		json.ServerError(w, r, err)
 		return
 	}
-	userInfo := userInfoResponse{UserID: fmt.Sprint(user.ID), UserName: user.Username, UserProfileID: fmt.Sprint(user.ID), UserEmail: user.Username}
+	userInfo := userInfoResponse{UserID: strconv.FormatInt(user.ID, 10), UserName: user.Username, UserProfileID: strconv.FormatInt(user.ID, 10), UserEmail: user.Username}
 	json.OK(w, r, userInfo)
 }
 
@@ -1048,7 +1047,7 @@ func (h *handler) streamItemIDsHandler(w http.ResponseWriter, r *http.Request) {
 	)
 
 	if len(rm.Streams) != 1 {
-		json.ServerError(w, r, fmt.Errorf("googlereader: only one stream type expected"))
+		json.ServerError(w, r, errors.New("googlereader: only one stream type expected"))
 		return
 	}
 	switch rm.Streams[0].Type {

+ 2 - 1
internal/googlereader/item.go

@@ -4,6 +4,7 @@
 package googlereader // import "miniflux.app/v2/internal/googlereader"
 
 import (
+	"errors"
 	"fmt"
 	"net/http"
 	"strconv"
@@ -58,7 +59,7 @@ func parseItemID(itemIDValue string) (int64, error) {
 func parseItemIDsFromRequest(r *http.Request) ([]int64, error) {
 	items := r.Form[paramItemIDs]
 	if len(items) == 0 {
-		return nil, fmt.Errorf("googlereader: no items requested")
+		return nil, errors.New("googlereader: no items requested")
 	}
 
 	itemIDs := make([]int64, len(items))

+ 2 - 2
internal/googlereader/request_modifier.go

@@ -49,8 +49,8 @@ func (r RequestModifiers) String() string {
 
 	results = append(results, fmt.Sprintf("Count: %d", r.Count))
 	results = append(results, fmt.Sprintf("Offset: %d", r.Offset))
-	results = append(results, fmt.Sprintf("Sort Direction: %s", r.SortDirection))
-	results = append(results, fmt.Sprintf("Continuation Token: %s", r.ContinuationToken))
+	results = append(results, "Sort Direction: "+r.SortDirection)
+	results = append(results, "Continuation Token: "+r.ContinuationToken)
 	results = append(results, fmt.Sprintf("Start Time: %d", r.StartTime))
 	results = append(results, fmt.Sprintf("Stop Time: %d", r.StopTime))
 

+ 2 - 1
internal/integration/apprise/apprise.go

@@ -6,6 +6,7 @@ package apprise
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"log/slog"
 	"net/http"
@@ -29,7 +30,7 @@ func NewClient(serviceURL, baseURL string) *Client {
 
 func (c *Client) SendNotification(feed *model.Feed, entries model.Entries) error {
 	if c.baseURL == "" || c.servicesURL == "" {
-		return fmt.Errorf("apprise: missing base URL or services URL")
+		return errors.New("apprise: missing base URL or services URL")
 	}
 
 	for _, entry := range entries {

+ 2 - 1
internal/integration/espial/espial.go

@@ -6,6 +6,7 @@ package espial // import "miniflux.app/v2/internal/integration/espial"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
@@ -27,7 +28,7 @@ func NewClient(baseURL, apiKey string) *Client {
 
 func (c *Client) CreateLink(entryURL, entryTitle, espialTags string) error {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("espial: missing base URL or API key")
+		return errors.New("espial: missing base URL or API key")
 	}
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/add")

+ 2 - 1
internal/integration/instapaper/instapaper.go

@@ -4,6 +4,7 @@
 package instapaper // import "miniflux.app/v2/internal/integration/instapaper"
 
 import (
+	"errors"
 	"fmt"
 	"net/http"
 	"net/url"
@@ -25,7 +26,7 @@ func NewClient(username, password string) *Client {
 
 func (c *Client) AddURL(entryURL, entryTitle string) error {
 	if c.username == "" || c.password == "" {
-		return fmt.Errorf("instapaper: missing username or password")
+		return errors.New("instapaper: missing username or password")
 	}
 
 	values := url.Values{}

+ 2 - 1
internal/integration/linkace/linkace.go

@@ -3,6 +3,7 @@ package linkace
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"strings"
@@ -28,7 +29,7 @@ func NewClient(baseURL, apiKey, tags string, private bool, checkDisabled bool) *
 
 func (c *Client) AddURL(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("linkace: missing base URL or API key")
+		return errors.New("linkace: missing base URL or API key")
 	}
 
 	tagsSplitFn := func(c rune) bool {

+ 2 - 1
internal/integration/linkding/linkding.go

@@ -6,6 +6,7 @@ package linkding // import "miniflux.app/v2/internal/integration/linkding"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"strings"
@@ -30,7 +31,7 @@ func NewClient(baseURL, apiKey, tags string, unread bool) *Client {
 
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("linkding: missing base URL or API key")
+		return errors.New("linkding: missing base URL or API key")
 	}
 
 	tagsSplitFn := func(c rune) bool {

+ 2 - 1
internal/integration/linktaco/linktaco.go

@@ -6,6 +6,7 @@ package linktaco // import "miniflux.app/v2/internal/integration/linktaco"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"strings"
@@ -44,7 +45,7 @@ func NewClient(apiToken, orgSlug, tags, visibility string) *Client {
 
 func (c *Client) CreateBookmark(entryURL, entryTitle, entryContent string) error {
 	if c.apiToken == "" || c.orgSlug == "" {
-		return fmt.Errorf("linktaco: missing API token or organization slug")
+		return errors.New("linktaco: missing API token or organization slug")
 	}
 
 	description := entryContent

+ 2 - 1
internal/integration/linkwarden/linkwarden.go

@@ -6,6 +6,7 @@ package linkwarden // import "miniflux.app/v2/internal/integration/linkwarden"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
@@ -27,7 +28,7 @@ func NewClient(baseURL, apiKey string) *Client {
 
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("linkwarden: missing base URL or API key")
+		return errors.New("linkwarden: missing base URL or API key")
 	}
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/v1/links")

+ 2 - 1
internal/integration/notion/notion.go

@@ -6,6 +6,7 @@ package notion
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
@@ -26,7 +27,7 @@ func NewClient(apiToken, pageID string) *Client {
 
 func (c *Client) UpdateDocument(entryURL string, entryTitle string) error {
 	if c.apiToken == "" || c.pageID == "" {
-		return fmt.Errorf("notion: missing API token or page ID")
+		return errors.New("notion: missing API token or page ID")
 	}
 
 	apiEndpoint := "https://api.notion.com/v1/blocks/" + c.pageID + "/children"

+ 2 - 1
internal/integration/nunuxkeeper/nunuxkeeper.go

@@ -6,6 +6,7 @@ package nunuxkeeper // import "miniflux.app/v2/internal/integration/nunuxkeeper"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
@@ -27,7 +28,7 @@ func NewClient(baseURL, apiKey string) *Client {
 
 func (c *Client) AddEntry(entryURL, entryTitle, entryContent string) error {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("nunux-keeper: missing base URL or API key")
+		return errors.New("nunux-keeper: missing base URL or API key")
 	}
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/v2/documents")

+ 2 - 2
internal/integration/pinboard/pinboard.go

@@ -14,8 +14,8 @@ import (
 	"miniflux.app/v2/internal/version"
 )
 
-var errPostNotFound = fmt.Errorf("pinboard: post not found")
-var errMissingCredentials = fmt.Errorf("pinboard: missing auth token")
+var errPostNotFound = errors.New("pinboard: post not found")
+var errMissingCredentials = errors.New("pinboard: missing auth token")
 
 const defaultClientTimeout = 10 * time.Second
 

+ 2 - 1
internal/integration/pushover/pushover.go

@@ -5,6 +5,7 @@ package pushover // import "miniflux.app/v2/internal/integration/pushover"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"log/slog"
 	"net/http"
@@ -72,7 +73,7 @@ func New(user, token string, priority int, device, urlPrefix string) *Client {
 
 func (c *Client) SendMessages(feed *model.Feed, entries model.Entries) error {
 	if c.token == "" || c.user == "" {
-		return fmt.Errorf("pushover token and user are required")
+		return errors.New("pushover token and user are required")
 	}
 	for _, entry := range entries {
 		msg := &Message{

+ 2 - 1
internal/integration/raindrop/raindrop.go

@@ -6,6 +6,7 @@ package raindrop // import "miniflux.app/v2/internal/integration/raindrop"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"strings"
@@ -29,7 +30,7 @@ func NewClient(token, collectionID, tags string) *Client {
 // https://developer.raindrop.io/v1/raindrops/single#create-raindrop
 func (c *Client) CreateRaindrop(entryURL, entryTitle string) error {
 	if c.token == "" {
-		return fmt.Errorf("raindrop: missing token")
+		return errors.New("raindrop: missing token")
 	}
 
 	var request *http.Request

+ 2 - 1
internal/integration/readeck/readeck.go

@@ -6,6 +6,7 @@ package readeck // import "miniflux.app/v2/internal/integration/readeck"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"mime/multipart"
 	"net/http"
@@ -31,7 +32,7 @@ func NewClient(baseURL, apiKey, labels string, onlyURL bool) *Client {
 
 func (c *Client) CreateBookmark(entryURL, entryTitle string, entryContent string) error {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("readeck: missing base URL or API key")
+		return errors.New("readeck: missing base URL or API key")
 	}
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/bookmarks/")

+ 2 - 1
internal/integration/readwise/readwise.go

@@ -8,6 +8,7 @@ package readwise // import "miniflux.app/v2/internal/integration/readwise"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
@@ -30,7 +31,7 @@ func NewClient(apiKey string) *Client {
 
 func (c *Client) CreateDocument(entryURL string) error {
 	if c.apiKey == "" {
-		return fmt.Errorf("readwise: missing API key")
+		return errors.New("readwise: missing API key")
 	}
 
 	requestBody, err := json.Marshal(&readwiseDocument{

+ 2 - 1
internal/integration/shaarli/shaarli.go

@@ -9,6 +9,7 @@ import (
 	"crypto/sha512"
 	"encoding/base64"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
@@ -30,7 +31,7 @@ func NewClient(baseURL, apiSecret string) *Client {
 
 func (c *Client) CreateLink(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.apiSecret == "" {
-		return fmt.Errorf("shaarli: missing base URL or API secret")
+		return errors.New("shaarli: missing base URL or API secret")
 	}
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/v1/links")

+ 2 - 1
internal/integration/shiori/shiori.go

@@ -6,6 +6,7 @@ package shiori // import "miniflux.app/v2/internal/integration/shiori"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
@@ -28,7 +29,7 @@ func NewClient(baseURL, username, password string) *Client {
 
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.username == "" || c.password == "" {
-		return fmt.Errorf("shiori: missing base URL, username or password")
+		return errors.New("shiori: missing base URL, username or password")
 	}
 
 	token, err := c.authenticate()

+ 2 - 1
internal/integration/wallabag/wallabag.go

@@ -6,6 +6,7 @@ package wallabag // import "miniflux.app/v2/internal/integration/wallabag"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"net/url"
@@ -34,7 +35,7 @@ func NewClient(baseURL, clientID, clientSecret, username, password, tags string,
 
 func (c *Client) CreateEntry(entryURL, entryTitle, entryContent string) error {
 	if c.baseURL == "" || c.clientID == "" || c.clientSecret == "" || c.username == "" || c.password == "" {
-		return fmt.Errorf("wallabag: missing base URL, client ID, client secret, username or password")
+		return errors.New("wallabag: missing base URL, client ID, client secret, username or password")
 	}
 
 	accessToken, err := c.getAccessToken()

+ 2 - 1
internal/integration/webhook/webhook.go

@@ -6,6 +6,7 @@ package webhook // import "miniflux.app/v2/internal/integration/webhook"
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
@@ -113,7 +114,7 @@ func (c *Client) SendNewEntriesWebhookEvent(feed *model.Feed, entries model.Entr
 
 func (c *Client) makeRequest(eventType string, payload any) error {
 	if c.webhookURL == "" {
-		return fmt.Errorf(`webhook: missing webhook URL`)
+		return errors.New(`webhook: missing webhook URL`)
 	}
 
 	requestBody, err := json.Marshal(payload)

+ 3 - 2
internal/reader/processor/bilibili.go

@@ -5,6 +5,7 @@ package processor // import "miniflux.app/v2/internal/reader/processor"
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"log/slog"
 	"regexp"
@@ -75,12 +76,12 @@ func fetchBilibiliWatchTime(websiteURL string) (int, error) {
 
 	data, ok := result["data"].(map[string]any)
 	if !ok {
-		return 0, fmt.Errorf("data field not found or not an object")
+		return 0, errors.New("data field not found or not an object")
 	}
 
 	duration, ok := data["duration"].(float64)
 	if !ok {
-		return 0, fmt.Errorf("duration not found or not a number")
+		return 0, errors.New("duration not found or not a number")
 	}
 	intDuration := int(duration)
 	durationMin := intDuration / 60

+ 2 - 1
internal/reader/readability/readability_test.go

@@ -5,6 +5,7 @@ package readability // import "miniflux.app/v2/internal/reader/readability"
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"os"
 	"strings"
@@ -2301,5 +2302,5 @@ func TestExtractContentWithBrokenReader(t *testing.T) {
 type brokenReader struct{}
 
 func (br *brokenReader) Read(p []byte) (n int, err error) {
-	return 0, fmt.Errorf("simulated read error")
+	return 0, errors.New("simulated read error")
 }

+ 3 - 3
internal/reader/sanitizer/srcset.go

@@ -4,7 +4,7 @@
 package sanitizer
 
 import (
-	"fmt"
+	"errors"
 	"strconv"
 	"strings"
 )
@@ -54,11 +54,11 @@ func parseImageCandidate(input string) (*imageCandidate, error) {
 		return &imageCandidate{ImageURL: parts[0]}, nil
 	case 2:
 		if !isValidWidthOrDensityDescriptor(parts[1]) {
-			return nil, fmt.Errorf(`srcset: invalid descriptor`)
+			return nil, errors.New(`srcset: invalid descriptor`)
 		}
 		return &imageCandidate{ImageURL: parts[0], Descriptor: parts[1]}, nil
 	default:
-		return nil, fmt.Errorf(`srcset: invalid number of descriptors`)
+		return nil, errors.New(`srcset: invalid number of descriptors`)
 	}
 }
 

+ 2 - 2
internal/reader/urlcleaner/urlcleaner.go

@@ -4,7 +4,7 @@
 package urlcleaner // import "miniflux.app/v2/internal/reader/urlcleaner"
 
 import (
-	"fmt"
+	"errors"
 	"net/url"
 	"strings"
 )
@@ -97,7 +97,7 @@ var trackingParamsOutbound = map[string]bool{
 
 func RemoveTrackingParameters(parsedFeedURL, parsedSiteURL, parsedInputUrl *url.URL) (string, error) {
 	if parsedFeedURL == nil || parsedSiteURL == nil || parsedInputUrl == nil {
-		return "", fmt.Errorf("urlcleaner: one of the URLs is nil")
+		return "", errors.New("urlcleaner: one of the URLs is nil")
 	}
 
 	queryParams := parsedInputUrl.Query()

+ 2 - 1
internal/storage/api_key.go

@@ -4,13 +4,14 @@
 package storage // import "miniflux.app/v2/internal/storage"
 
 import (
+	"errors"
 	"fmt"
 
 	"miniflux.app/v2/internal/crypto"
 	"miniflux.app/v2/internal/model"
 )
 
-var ErrAPIKeyNotFound = fmt.Errorf("store: API Key not found")
+var ErrAPIKeyNotFound = errors.New("store: API Key not found")
 
 // APIKeyExists checks if an API Key with the same description exists.
 func (s *Storage) APIKeyExists(userID int64, description string) bool {

+ 3 - 2
internal/storage/user_session.go

@@ -6,6 +6,7 @@ package storage // import "miniflux.app/v2/internal/storage"
 import (
 	"crypto/rand"
 	"database/sql"
+	"errors"
 	"fmt"
 	"time"
 
@@ -138,7 +139,7 @@ func (s *Storage) RemoveUserSessionByToken(userID int64, token string) error {
 	}
 
 	if count != 1 {
-		return fmt.Errorf(`store: nothing has been removed`)
+		return errors.New(`store: nothing has been removed`)
 	}
 
 	return nil
@@ -158,7 +159,7 @@ func (s *Storage) RemoveUserSessionByID(userID, sessionID int64) error {
 	}
 
 	if count != 1 {
-		return fmt.Errorf(`store: nothing has been removed`)
+		return errors.New(`store: nothing has been removed`)
 	}
 
 	return nil

+ 2 - 1
internal/systemd/systemd.go

@@ -4,6 +4,7 @@
 package systemd // import "miniflux.app/v2/internal/systemd"
 
 import (
+	"errors"
 	"fmt"
 	"net"
 	"os"
@@ -40,7 +41,7 @@ func WatchdogInterval() (time.Duration, error) {
 	}
 
 	if s <= 0 {
-		return 0, fmt.Errorf(`systemd: error WATCHDOG_USEC must be a positive number`)
+		return 0, errors.New(`systemd: error WATCHDOG_USEC must be a positive number`)
 	}
 
 	return time.Duration(s) * time.Microsecond, nil

+ 3 - 2
internal/template/functions.go

@@ -4,6 +4,7 @@
 package template // import "miniflux.app/v2/internal/template"
 
 import (
+	"errors"
 	"fmt"
 	"html/template"
 	"math"
@@ -153,13 +154,13 @@ func csp(user *model.User, nonce string) string {
 
 func dict(values ...any) (map[string]any, error) {
 	if len(values)%2 != 0 {
-		return nil, fmt.Errorf("dict expects an even number of arguments")
+		return nil, errors.New("dict expects an even number of arguments")
 	}
 	dict := make(map[string]any, len(values)/2)
 	for i := 0; i < len(values); i += 2 {
 		key, ok := values[i].(string)
 		if !ok {
-			return nil, fmt.Errorf("dict keys must be strings")
+			return nil, errors.New("dict keys must be strings")
 		}
 		dict[key] = values[i+1]
 	}

+ 3 - 2
internal/urllib/url.go

@@ -4,6 +4,7 @@
 package urllib // import "miniflux.app/v2/internal/urllib"
 
 import (
+	"errors"
 	"fmt"
 	"net/url"
 	"strings"
@@ -103,11 +104,11 @@ func DomainWithoutWWW(websiteURL string) string {
 // JoinBaseURLAndPath returns a URL string with the provided path elements joined together.
 func JoinBaseURLAndPath(baseURL, path string) (string, error) {
 	if baseURL == "" {
-		return "", fmt.Errorf("empty base URL")
+		return "", errors.New("empty base URL")
 	}
 
 	if path == "" {
-		return "", fmt.Errorf("empty path")
+		return "", errors.New("empty path")
 	}
 
 	_, err := url.Parse(baseURL)

+ 2 - 2
internal/validator/enclosure.go

@@ -4,14 +4,14 @@
 package validator
 
 import (
-	"fmt"
+	"errors"
 
 	"miniflux.app/v2/internal/model"
 )
 
 func ValidateEnclosureUpdateRequest(request *model.EnclosureUpdateRequest) error {
 	if request.MediaProgression < 0 {
-		return fmt.Errorf(`media progression must an positive integer`)
+		return errors.New(`media progression must an positive integer`)
 	}
 
 	return nil

+ 5 - 4
internal/validator/entry.go

@@ -4,6 +4,7 @@
 package validator // import "miniflux.app/v2/internal/validator"
 
 import (
+	"errors"
 	"fmt"
 
 	"miniflux.app/v2/internal/model"
@@ -12,7 +13,7 @@ import (
 // ValidateEntriesStatusUpdateRequest validates a status update for a list of entries.
 func ValidateEntriesStatusUpdateRequest(request *model.EntriesStatusUpdateRequest) error {
 	if len(request.EntryIDs) == 0 {
-		return fmt.Errorf(`the list of entries cannot be empty`)
+		return errors.New(`the list of entries cannot be empty`)
 	}
 
 	return ValidateEntryStatus(request.Status)
@@ -35,17 +36,17 @@ func ValidateEntryOrder(order string) error {
 		return nil
 	}
 
-	return fmt.Errorf(`invalid entry order, valid order values are: "id", "status", "changed_at", "published_at", "created_at", "category_title", "category_id", "title", "author"`)
+	return errors.New(`invalid entry order, valid order values are: "id", "status", "changed_at", "published_at", "created_at", "category_title", "category_id", "title", "author"`)
 }
 
 // ValidateEntryModification makes sure the entry modification is valid.
 func ValidateEntryModification(request *model.EntryUpdateRequest) error {
 	if request.Title != nil && *request.Title == "" {
-		return fmt.Errorf(`the entry title cannot be empty`)
+		return errors.New(`the entry title cannot be empty`)
 	}
 
 	if request.Content != nil && *request.Content == "" {
-		return fmt.Errorf(`the entry content cannot be empty`)
+		return errors.New(`the entry content cannot be empty`)
 	}
 
 	return nil

+ 4 - 4
internal/validator/validator.go

@@ -4,7 +4,7 @@
 package validator // import "miniflux.app/v2/internal/validator"
 
 import (
-	"fmt"
+	"errors"
 	"net/url"
 	"regexp"
 	"strings"
@@ -15,11 +15,11 @@ var domainRegex = regexp.MustCompile(`^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.
 // ValidateRange makes sure the offset/limit values are valid.
 func ValidateRange(offset, limit int) error {
 	if offset < 0 {
-		return fmt.Errorf(`offset value should be >= 0`)
+		return errors.New(`offset value should be >= 0`)
 	}
 
 	if limit < 0 {
-		return fmt.Errorf(`limit value should be >= 0`)
+		return errors.New(`limit value should be >= 0`)
 	}
 
 	return nil
@@ -32,7 +32,7 @@ func ValidateDirection(direction string) error {
 		return nil
 	}
 
-	return fmt.Errorf(`invalid direction, valid direction values are: "asc" or "desc"`)
+	return errors.New(`invalid direction, valid direction values are: "asc" or "desc"`)
 }
 
 // IsValidRegex verifies if the regex can be compiled.