Repository: kopia/kopia
Pull request #4159 (2024-10-06 00:29:25)

refactor(general): use `context.WithoutCancel(ctx)` from the standard library
Use [`context.WithoutCancel`](https://pkg.go.dev/context#WithoutCancel) introduced in Go 1.21.

Removes `internal/ctxutil` package with equivalent implementation.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/kopia/kopia/pull/4159?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) Report
Attention: Patch coverage is `60.00000%` with `4 lines` in your changes missing coverage. Please review.
> Project coverage is 77.21%. Comparing base [(`cb455c6`)](https://app.codecov.io/gh/kopia/kopia/commit/cb455c699a04e54cb47e25a676d7d65063ce883e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) to head [(`2e384bb`)](https://app.codecov.io/gh/kopia/kopia/commit/2e384bb77ebd872e0a1399f0c1a93c594eb85a7f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia).
> Report is 280 commits behind head on master.

| [Files with missing lines](https://app.codecov.io/gh/kopia/kopia/pull/4159?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) | Patch % | Lines |
|---|---|---|
| [cli/command\_server\_start.go](https://app.codecov.io/gh/kopia/kopia/pull/4159?src=pr&el=tree&filepath=cli%2Fcommand_server_start.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-Y2xpL2NvbW1hbmRfc2VydmVyX3N0YXJ0Lmdv) | 0.00% | [3 Missing :warning: ](https://app.codecov.io/gh/kopia/kopia/pull/4159?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) |
| [repo/grpc\_repository\_client.go](https://app.codecov.io/gh/kopia/kopia/pull/4159?src=pr&el=tree&filepath=repo%2Fgrpc_repository_client.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-cmVwby9ncnBjX3JlcG9zaXRvcnlfY2xpZW50Lmdv) | 50.00% | [0 Missing and 1 partial :warning: ](https://app.codecov.io/gh/kopia/kopia/pull/4159?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4159      +/-   ##
==========================================
+ Coverage   75.86%   77.21%   +1.35%     
==========================================
  Files         470      483      +13     
  Lines       37301    28860    -8441     
==========================================
- Hits        28299    22285    -6014     
+ Misses       7071     4667    -2404     
+ Partials     1931     1908      -23     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/kopia/kopia/pull/4159?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia).


Patch:
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 7164a451..f5b92393 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -37,10 +37,12 @@ jobs:
       id: go
       if: ${{ !contains(matrix.os, 'ARMHF') }}
     - id: govulncheck
-      uses: golang/govulncheck-action@dd0578b371c987f96d1185abb54344b44352bd58 # v1.0.3
+      uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee # v1.0.4
       with:
-        repo-checkout: false
         cache: false
+        go-version-input:
+        go-version-file: 'go.mod'
+        repo-checkout: false
     - name: Lint
       run: make lint
     - name: Check Locks
diff --git a/cli/app.go b/cli/app.go
index cec3e79f..37b004fa 100644
--- a/cli/app.go
+++ b/cli/app.go
@@ -380,7 +380,7 @@ func safetyFlagVar(cmd *kingpin.CmdClause, result *maintenance.SafetyParameters)
 	cmd.Flag("safety", "Safety level").Default("full").PreAction(func(_ *kingpin.ParseContext) error {
 		r, ok := safetyByName[str]
 		if !ok {
-			return errors.Errorf("unhandled safety level")
+			return errors.New("unhandled safety level")
 		}
 
 		*result = r
@@ -435,7 +435,7 @@ func assertDirectRepository(act func(ctx context.Context, rep repo.DirectReposit
 		// but will fail in the future when we have remote repository implementation
 		lr, ok := rep.(repo.DirectRepository)
 		if !ok {
-			return errors.Errorf("operation supported only on direct repository")
+			return errors.New("operation supported only on direct repository")
 		}
 
 		return act(ctx, lr)
@@ -611,7 +611,7 @@ func (c *App) advancedCommand(ctx context.Context) {
 
 `)
 
-		c.exitWithError(errors.Errorf("advanced commands are disabled"))
+		c.exitWithError(errors.New("advanced commands are disabled"))
 	}
 }
 
diff --git a/cli/command_acl_enable.go b/cli/command_acl_enable.go
index 16942552..df0f019d 100644
--- a/cli/command_acl_enable.go
+++ b/cli/command_acl_enable.go
@@ -27,7 +27,7 @@ func (c *commandACLEnable) run(ctx context.Context, rep repo.RepositoryWriter) e
 	}
 
 	if len(entries) != 0 && !c.reset {
-		return errors.Errorf("ACLs already enabled")
+		return errors.New("ACLs already enabled")
 	}
 
 	if c.reset {
diff --git a/cli/command_benchmark_compression.go b/cli/command_benchmark_compression.go
index a33d2751..61a66726 100644
--- a/cli/command_benchmark_compression.go
+++ b/cli/command_benchmark_compression.go
@@ -115,7 +115,7 @@ func (c *commandBenchmarkCompression) run(ctx context.Context) error {
 	}
 
 	if len(data) == 0 {
-		return errors.Errorf("empty data file")
+		return errors.New("empty data file")
 	}
 
 	repeatCount := c.repeat
diff --git a/cli/command_blob_shards_modify.go b/cli/command_blob_shards_modify.go
index 6715b837..970c58b9 100644
--- a/cli/command_blob_shards_modify.go
+++ b/cli/command_blob_shards_modify.go
@@ -73,7 +73,7 @@ func parseShardSpec(shards string) ([]int, error) {
 
 		v, err := strconv.Atoi(p)
 		if err != nil || v < 0 {
-			return nil, errors.Errorf("invalid shard specification")
+			return nil, errors.New("invalid shard specification")
 		}
 
 		result = append(result, v)
@@ -98,7 +98,7 @@ func (c *commandBlobShardsModify) applyParameterChangesFromFlags(p *sharded.Para
 	if c.defaultShardSpec != "" {
 		v, err := parseShardSpec(c.defaultShardSpec)
 		if err != nil {
-			return errors.Errorf("invalid --default-shards")
+			return errors.New("invalid --default-shards")
 		}
 
 		p.DefaultShards = v
diff --git a/cli/command_cache_set.go b/cli/command_cache_set.go
index fb08001d..ad22a856 100644
--- a/cli/command_cache_set.go
+++ b/cli/command_cache_set.go
@@ -132,7 +132,7 @@ func (c *commandCacheSetParams) run(ctx context.Context, _ repo.RepositoryWriter
 	}
 
 	if changed == 0 {
-		return errors.Errorf("no changes")
+		return errors.New("no changes")
 	}
 
 	//nolint:wrapcheck
diff --git a/cli/command_index_epoch_list.go b/cli/command_index_epoch_list.go
index 3ac5ac65..b8101a5e 100644
--- a/cli/command_index_epoch_list.go
+++ b/cli/command_index_epoch_list.go
@@ -29,7 +29,7 @@ func (c *commandIndexEpochList) run(ctx context.Context, rep repo.DirectReposito
 	}
 
 	if !ok {
-		return errors.Errorf("epoch manager is not active")
+		return errors.New("epoch manager is not active")
 	}
 
 	snap, err := emgr.Current(ctx)
diff --git a/cli/command_index_inspect.go b/cli/command_index_inspect.go
index dd6b8bf4..7d7121d9 100644
--- a/cli/command_index_inspect.go
+++ b/cli/command_index_inspect.go
@@ -70,7 +70,7 @@ func (c *commandIndexInspect) runWithOutput(ctx context.Context, rep repo.Direct
 			}
 		}
 	default:
-		return errors.Errorf("must pass either --all, --active or provide a list of blob IDs to inspect")
+		return errors.New("must pass either --all, --active or provide a list of blob IDs to inspect")
 	}
 
 	return nil
diff --git a/cli/command_logs_show.go b/cli/command_logs_show.go
index 278e55da..f0726fd4 100644
--- a/cli/command_logs_show.go
+++ b/cli/command_logs_show.go
@@ -49,7 +49,7 @@ func (c *commandLogsShow) run(ctx context.Context, rep repo.DirectRepository) er
 	}
 
 	if len(sessions) == 0 {
-		return errors.Errorf("no logs found")
+		return errors.New("no logs found")
 	}
 
 	// by default show latest one
diff --git a/cli/command_ls.go b/cli/command_ls.go
index 25078855..651d3470 100644
--- a/cli/command_ls.go
+++ b/cli/command_ls.go
@@ -89,7 +89,7 @@ func (c *commandList) listDirectory(ctx context.Context, d fs.Directory, prefix,
 func (c *commandList) printDirectoryEntry(ctx context.Context, e fs.Entry, prefix, indent string) error {
 	hoid, ok := e.(object.HasObjectID)
 	if !ok {
-		return errors.Errorf("entry without object ID")
+		return errors.New("entry without object ID")
 	}
 
 	objectID := hoid.ObjectID()
diff --git a/cli/command_maintenance_set.go b/cli/command_maintenance_set.go
index c5b25aab..4dbd6e81 100644
--- a/cli/command_maintenance_set.go
+++ b/cli/command_maintenance_set.go
@@ -190,7 +190,7 @@ func (c *commandMaintenanceSet) run(ctx context.Context, rep repo.DirectReposito
 	}
 
 	if !changedParams && !changedSchedule {
-		return errors.Errorf("no changes specified")
+		return errors.New("no changes specified")
 	}
 
 	blobCfg, err := rep.FormatManager().BlobCfgBlob(ctx)
diff --git a/cli/command_repository_connect_from_config.go b/cli/command_repository_connect_from_config.go
index b2b2fd1a..56e215f7 100644
--- a/cli/command_repository_connect_from_config.go
+++ b/cli/command_repository_connect_from_config.go
@@ -63,7 +63,7 @@ func (c *storageFromConfigFlags) connectToStorageFromConfigFile(ctx context.Cont
 	}
 
 	if cfg.Storage == nil {
-		return nil, errors.Errorf("connection file does not specify blob storage connection parameters, kopia server connections are not supported")
+		return nil, errors.New("connection file does not specify blob storage connection parameters, kopia server connections are not supported")
 	}
 
 	//nolint:wrapcheck
diff --git a/cli/command_repository_create.go b/cli/command_repository_create.go
index 4c5ab701..985676ef 100644
--- a/cli/command_repository_create.go
+++ b/cli/command_repository_create.go
@@ -100,7 +100,7 @@ func (c *commandRepositoryCreate) newRepositoryOptionsFromFlags() *repo.NewRepos
 }
 
 func (c *commandRepositoryCreate) ensureEmpty(ctx context.Context, s blob.Storage) error {
-	hasDataError := errors.Errorf("has data")
+	hasDataError := errors.New("has data")
 
 	err := s.ListBlobs(ctx, "", func(_ blob.Metadata) error {
 		return hasDataError
diff --git a/cli/command_repository_set_client.go b/cli/command_repository_set_client.go
index 3595e230..96dad21b 100644
--- a/cli/command_repository_set_client.go
+++ b/cli/command_repository_set_client.go
@@ -113,7 +113,7 @@ func (c *commandRepositorySetClient) run(ctx context.Context, rep repo.Repositor
 	}
 
 	if !anyChange {
-		return errors.Errorf("no changes")
+		return errors.New("no changes")
 	}
 
 	//nolint:wrapcheck
diff --git a/cli/command_repository_set_parameters.go b/cli/command_repository_set_parameters.go
index 71131c07..5baf3399 100644
--- a/cli/command_repository_set_parameters.go
+++ b/cli/command_repository_set_parameters.go
@@ -192,7 +192,7 @@ func (c *commandRepositorySetParameters) run(ctx context.Context, rep repo.Direc
 		if c.indexFormatVersion > mp.IndexVersion {
 			setIntParameter(ctx, c.indexFormatVersion, "index format version", &mp.IndexVersion, &anyChange)
 		} else {
-			return errors.Errorf("index format version can only be upgraded")
+			return errors.New("index format version can only be upgraded")
 		}
 	}
 
diff --git a/cli/command_repository_sync.go b/cli/command_repository_sync.go
index 9b79e107..4aeeb9b2 100644
--- a/cli/command_repository_sync.go
+++ b/cli/command_repository_sync.go
@@ -69,7 +69,7 @@ func (c *commandRepositorySyncTo) setup(svc advancedAppServices, parent commandP
 
 				dr, ok := rep.(repo.DirectRepository)
 				if !ok {
-					return errors.Errorf("sync only supports directly-connected repositories")
+					return errors.New("sync only supports directly-connected repositories")
 				}
 
 				return c.runSyncWithStorage(ctx, dr.BlobReader(), st)
@@ -356,7 +356,7 @@ func (c *commandRepositorySyncTo) ensureRepositoriesHaveSameFormatBlob(ctx conte
 		// target does not have format blob, save it there first.
 		if errors.Is(err, blob.ErrBlobNotFound) {
 			if c.repositorySyncDestinationMustExist {
-				return errors.Errorf("destination repository does not have a format blob")
+				return errors.New("destination repository does not have a format blob")
 			}
 
 			return errors.Wrap(dst.PutBlob(ctx, format.KopiaRepositoryBlobID, srcData.Bytes(), blob.PutOptions{}), "error saving format blob")
@@ -379,7 +379,7 @@ func (c *commandRepositorySyncTo) ensureRepositoriesHaveSameFormatBlob(ctx conte
 		return nil
 	}
 
-	return errors.Errorf("destination repository contains incompatible data")
+	return errors.New("destination repository contains incompatible data")
 }
 
 func parseUniqueID(r gather.Bytes) (string, error) {
@@ -392,7 +392,7 @@ func parseUniqueID(r gather.Bytes) (string, error) {
 	}
 
 	if f.UniqueID == "" {
-		return "", errors.Errorf("unique ID not found")
+		return "", errors.New("unique ID not found")
 	}
 
 	return f.UniqueID, nil
diff --git a/cli/command_repository_upgrade.go b/cli/command_repository_upgrade.go
index 446ea3d0..db867cf2 100644
--- a/cli/command_repository_upgrade.go
+++ b/cli/command_repository_upgrade.go
@@ -426,7 +426,7 @@ func (c *commandRepositoryUpgrade) drainAllClients(ctx context.Context, rep repo
 
 		// TODO: this can get stuck
 		if !c.sleepWithContext(ctx, l.StatusPollInterval) {
-			return errors.Errorf("upgrade drain interrupted")
+			return errors.New("upgrade drain interrupted")
 		}
 	}
 
diff --git a/cli/command_restore.go b/cli/command_restore.go
index 4fe24e62..6a305f05 100644
--- a/cli/command_restore.go
+++ b/cli/command_restore.go
@@ -242,7 +242,7 @@ func (c *commandRestore) constructTargetPairs(rep repo.Repository) error {
 	}
 
 	// Some undefined mixture of placeholders and other arguments.
-	return errors.Errorf("restore requires a source and targetpath or placeholders")
+	return errors.New("restore requires a source and targetpath or placeholders")
 }
 
 func (c *commandRestore) restoreOutput(ctx context.Context, rep repo.Repository) (restore.Output, error) {
@@ -473,7 +473,7 @@ func (c *commandRestore) tryToConvertPathToID(ctx context.Context, rep repo.Repo
 	}
 
 	if si.Path == "" {
-		return "", errors.Errorf("the source must contain a path element")
+		return "", errors.New("the source must contain a path element")
 	}
 
 	manifestIDs, err := findSnapshotsForSource(ctx, rep, si, map[string]string{})
diff --git a/cli/command_server.go b/cli/command_server.go
index 8812c618..a4db704f 100644
--- a/cli/command_server.go
+++ b/cli/command_server.go
@@ -76,7 +76,7 @@ func (c *commandServer) setup(svc advancedAppServices, parent commandParent) {
 
 func (c *serverClientFlags) serverAPIClientOptions() (apiclient.Options, error) {
 	if c.serverAddress == "" {
-		return apiclient.Options{}, errors.Errorf("missing server address")
+		return apiclient.Options{}, errors.New("missing server address")
 	}
 
 	return apiclient.Options{
diff --git a/cli/command_server_source_manager_action.go b/cli/command_server_source_manager_action.go
index df7b98b4..39e129f4 100644
--- a/cli/command_server_source_manager_action.go
+++ b/cli/command_server_source_manager_action.go
@@ -39,7 +39,7 @@ func (c *commandServerSourceManagerAction) triggerActionOnMatchingSources(ctx co
 
 	if !c.all {
 		if c.source == "" {
-			return errors.Errorf("must specify source or --all")
+			return errors.New("must specify source or --all")
 		}
 
 		absPath, err := filepath.Abs(c.source)
diff --git a/cli/command_server_start.go b/cli/command_server_start.go
index 5e7211a5..4ecd14e0 100644
--- a/cli/command_server_start.go
+++ b/cli/command_server_start.go
@@ -20,7 +20,6 @@
 	htpasswd "github.com/tg123/go-htpasswd"
 
 	"github.com/kopia/kopia/internal/auth"
-	"github.com/kopia/kopia/internal/ctxutil"
 	"github.com/kopia/kopia/internal/server"
 	"github.com/kopia/kopia/repo"
 )
@@ -256,11 +255,12 @@ func (c *commandServerStart) run(ctx context.Context) (reterr error) {
 	if c.serverStartShutdownWhenStdinClosed {
 		log(ctx).Info("Server will close when stdin is closed...")
 
-		ctxutil.GoDetached(ctx, func(ctx context.Context) {
+		go func() {
+			ctx := context.WithoutCancel(ctx)
 			// consume all stdin and close the server when it closes
 			io.Copy(io.Discard, os.Stdin) //nolint:errcheck
 			shutdownHTTPServer(ctx, httpServer)
-		})
+		}()
 	}
 
 	onExternalConfigReloadRequest(srv.Refresh)
@@ -322,7 +322,7 @@ func (c *commandServerStart) getAuthenticator(ctx context.Context) (auth.Authent
 	switch {
 	case c.serverStartWithoutPassword:
 		if !c.serverStartInsecure {
-			return nil, errors.Errorf("--without-password specified without --insecure, refusing to start server")
+			return nil, errors.New("--without-password specified without --insecure, refusing to start server")
 		}
 
 		return nil, nil
diff --git a/cli/command_server_tls.go b/cli/command_server_tls.go
index 2cdf0a35..53c38e67 100644
--- a/cli/command_server_tls.go
+++ b/cli/command_server_tls.go
@@ -162,7 +162,7 @@ func (c *commandServerStart) startServerWithOptionalTLSAndListener(ctx context.C
 
 	default:
 		if !c.serverStartInsecure {
-			return errors.Errorf("TLS not configured. To start server without encryption pass --insecure")
+			return errors.New("TLS not configured. To start server without encryption pass --insecure")
 		}
 
 		fmt.Fprintf(c.out.stderr(), "SERVER ADDRESS: %shttp://%v\n", udsPfx, httpServer.Addr) //nolint:errcheck
diff --git a/cli/command_snapshot_copy_move_history.go b/cli/command_snapshot_copy_move_history.go
index 42e7c45b..7dffd941 100644
--- a/cli/command_snapshot_copy_move_history.go
+++ b/cli/command_snapshot_copy_move_history.go
@@ -178,13 +178,13 @@ func (c *commandSnapshotCopyMoveHistory) getCopySourceAndDestination(rep repo.Re
 	if di.Path != "" && si.Path == "" {
 		// it is illegal to specify source without path, but destination with a path
 		// as it would result in multiple individual paths being squished together.
-		return si, di, errors.Errorf("path specified on destination but not source")
+		return si, di, errors.New("path specified on destination but not source")
 	}
 
 	if di.UserName != "" && si.UserName == "" {
 		// it is illegal to specify source without username, but destination with a username
 		// as it would result in multiple individual paths being squished together.
-		return si, di, errors.Errorf("username specified on destination but not source")
+		return si, di, errors.New("username specified on destination but not source")
 	}
 
 	return si, di, nil
diff --git a/cli/command_snapshot_fix_remove_files.go b/cli/command_snapshot_fix_remove_files.go
index 80cd7eb3..9dbe5630 100644
--- a/cli/command_snapshot_fix_remove_files.go
+++ b/cli/command_snapshot_fix_remove_files.go
@@ -54,7 +54,7 @@ func (c *commandSnapshotFixRemoveFiles) rewriteEntry(ctx context.Context, dirRel
 
 func (c *commandSnapshotFixRemoveFiles) run(ctx context.Context, rep repo.RepositoryWriter) error {
 	if len(c.removeObjectIDs)+len(c.removeFilesByName) == 0 {
-		return errors.Errorf("must specify files to remove")
+		return errors.New("must specify files to remove")
 	}
 
 	return c.common.rewriteMatchingSnapshots(ctx, rep, c.rewriteEntry)
diff --git a/cli/command_snapshot_pin.go b/cli/command_snapshot_pin.go
index a1892949..4b28db70 100644
--- a/cli/command_snapshot_pin.go
+++ b/cli/command_snapshot_pin.go
@@ -27,7 +27,7 @@ func (c *commandSnapshotPin) setup(svc appServices, parent commandParent) {
 
 func (c *commandSnapshotPin) run(ctx context.Context, rep repo.RepositoryWriter) error {
 	if len(c.addPins)+len(c.removePins) == 0 {
-		return errors.Errorf("must specify --add and/or --remove")
+		return errors.New("must specify --add and/or --remove")
 	}
 
 	for _, id := range c.snapshotIDs {
diff --git a/cli/command_user_add_set.go b/cli/command_user_add_set.go
index 64057510..4131e755 100644
--- a/cli/command_user_add_set.go
+++ b/cli/command_user_add_set.go
@@ -93,7 +93,7 @@ func (c *commandServerUserAddSet) runServerUserAddSet(ctx context.Context, rep r
 	}
 
 	if !changed && !c.isNew {
-		return errors.Errorf("no change")
+		return errors.New("no change")
 	}
 
 	if err := user.SetUserProfile(ctx, rep, up); err != nil {
diff --git a/cli/config.go b/cli/config.go
index 40ad3105..cab86e57 100644
--- a/cli/config.go
+++ b/cli/config.go
@@ -54,7 +54,7 @@ func (c *App) openRepository(ctx context.Context, required bool) (repo.Repositor
 			return nil, nil
 		}
 
-		return nil, errors.Errorf("repository is not connected. See https://kopia.io/docs/repositories/")
+		return nil, errors.New("repository is not connected. See https://kopia.io/docs/repositories/")
 	}
 
 	c.maybePrintUpdateNotification(ctx)
diff --git a/cli/observability_flags.go b/cli/observability_flags.go
index c1b623cf..48b31b62 100644
--- a/cli/observability_flags.go
+++ b/cli/observability_flags.go
@@ -169,7 +169,7 @@ func (c *observabilityFlags) maybeStartMetricsPusher(ctx context.Context) error
 
 		parts := strings.SplitN(g, ":", nParts)
 		if len(parts) != nParts {
-			return errors.Errorf("grouping must be name:value")
+			return errors.New("grouping must be name:value")
 		}
 
 		name := parts[0]
@@ -196,7 +196,7 @@ func (c *observabilityFlags) maybeStartMetricsPusher(ctx context.Context) error
 
 func (c *observabilityFlags) maybeStartTraceExporter(ctx context.Context) error {
 	if c.enableJaeger {
-		return errors.Errorf("Flag '--enable-jaeger-collector' is no longer supported, use '--otlp' instead. See https://github.com/kopia/kopia/pull/3264 for more information")
+		return errors.New("Flag '--enable-jaeger-collector' is no longer supported, use '--otlp' instead. See https://github.com/kopia/kopia/pull/3264 for more information")
 	}
 
 	if !c.otlpTrace {
diff --git a/cli/storage_filesystem.go b/cli/storage_filesystem.go
index 18836c04..9d8068ce 100644
--- a/cli/storage_filesystem.go
+++ b/cli/storage_filesystem.go
@@ -46,7 +46,7 @@ func (c *storageFilesystemFlags) Connect(ctx context.Context, isCreate bool, for
 	fso.Path = ospath.ResolveUserFriendlyPath(fso.Path, false)
 
 	if !ospath.IsAbs(fso.Path) {
-		return nil, errors.Errorf("filesystem repository path must be absolute")
+		return nil, errors.New("filesystem repository path must be absolute")
 	}
 
 	if v := c.connectOwnerUID; v != "" {
diff --git a/cli/storage_s3.go b/cli/storage_s3.go
index 77f1b9ce..89f947c8 100644
--- a/cli/storage_s3.go
+++ b/cli/storage_s3.go
@@ -55,7 +55,7 @@ func (c *storageS3Flags) Setup(svc StorageProviderServices, cmd *kingpin.CmdClau
 
 func (c *storageS3Flags) preActionLoadPEMPath(_ *kingpin.ParseContext) error {
 	if len(c.s3options.RootCA) > 0 {
-		return errors.Errorf("root-ca-pem-base64 and root-ca-pem-path are mutually exclusive")
+		return errors.New("root-ca-pem-base64 and root-ca-pem-path are mutually exclusive")
 	}
 
 	data, err := os.ReadFile(c.rootCaPemPath) //#nosec
diff --git a/cli/storage_sftp.go b/cli/storage_sftp.go
index d7e8165a..4ede083c 100644
--- a/cli/storage_sftp.go
+++ b/cli/storage_sftp.go
@@ -86,7 +86,7 @@ func (c *storageSFTPFlags) getOptions(formatVersion int) (*sftp.Options, error)
 			sftpo.Keyfile = a
 
 		default:
-			return nil, errors.Errorf("must provide either --sftp-password, --keyfile or --key-data")
+			return nil, errors.New("must provide either --sftp-password, --keyfile or --key-data")
 		}
 
 		switch {
@@ -100,7 +100,7 @@ func (c *storageSFTPFlags) getOptions(formatVersion int) (*sftp.Options, error)
 
 			sftpo.KnownHostsFile = a
 		default:
-			return nil, errors.Errorf("must provide either --known-hosts or --known-hosts-data")
+			return nil, errors.New("must provide either --known-hosts or --known-hosts-data")
 		}
 	}
 
diff --git a/cli/update_check.go b/cli/update_check.go
index 5119afbd..4089f02d 100644
--- a/cli/update_check.go
+++ b/cli/update_check.go
@@ -161,7 +161,7 @@ func (c *App) maybeCheckForUpdates(ctx context.Context) (string, error) {
 	if v := os.Getenv(c.EnvName(checkForUpdatesEnvar)); v != "" {
 		// see if environment variable is set to false.
 		if b, err := strconv.ParseBool(v); err == nil && !b {
-			return "", errors.Errorf("update check disabled")
+			return "", errors.New("update check disabled")
 		}
 	}
 
diff --git a/fs/entry.go b/fs/entry.go
index f0248e4a..30def541 100644
--- a/fs/entry.go
+++ b/fs/entry.go
@@ -13,7 +13,7 @@
 const ModBits = os.ModePerm | os.ModeSetgid | os.ModeSetuid | os.ModeSticky
 
 // ErrUnknown is returned by ErrorEntry.ErrorInfo() to indicate that type of an entry is unknown.
-var ErrUnknown = errors.Errorf("unknown or unsupported entry type")
+var ErrUnknown = errors.New("unknown or unsupported entry type")
 
 // Entry represents a filesystem entry, which can be Directory, File, or Symlink.
 type Entry interface {
diff --git a/fs/ignorefs/ignorefs.go b/fs/ignorefs/ignorefs.go
index 47773440..b86c98cb 100644
--- a/fs/ignorefs/ignorefs.go
+++ b/fs/ignorefs/ignorefs.go
@@ -85,7 +85,7 @@ func isCorrectCacheDirSignature(ctx context.Context, f fs.File) error {
 	)
 
 	if f.Size() < int64(validSignatureLen) {
-		return errors.Errorf("cache dir marker file too short")
+		return errors.New("cache dir marker file too short")
 	}
 
 	r, err := f.Open(ctx)
@@ -102,7 +102,7 @@ func isCorrectCacheDirSignature(ctx context.Context, f fs.File) error {
 	}
 
 	if string(sig) != validSignature {
-		return errors.Errorf("invalid cache dir marker file signature")
+		return errors.New("invalid cache dir marker file signature")
 	}
 
 	return nil
diff --git a/go.mod b/go.mod
index 9f195627..0f7e600e 100644
--- a/go.mod
+++ b/go.mod
@@ -28,7 +28,7 @@ require (
 	github.com/klauspost/compress v1.17.10
 	github.com/klauspost/pgzip v1.2.6
 	github.com/klauspost/reedsolomon v1.12.4
-	github.com/kopia/htmluibuild v0.0.1-0.20241001052939-6d8c75cf019a
+	github.com/kopia/htmluibuild v0.0.1-0.20241006020113-c37037c013ee
 	github.com/kylelemons/godebug v1.1.0
 	github.com/mattn/go-colorable v0.1.13
 	github.com/minio/minio-go/v7 v7.0.77
diff --git a/go.sum b/go.sum
index 9b1ced70..437d5f5c 100644
--- a/go.sum
+++ b/go.sum
@@ -175,8 +175,8 @@ github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU
 github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
 github.com/klauspost/reedsolomon v1.12.4 h1:5aDr3ZGoJbgu/8+j45KtUJxzYm8k08JGtB9Wx1VQ4OA=
 github.com/klauspost/reedsolomon v1.12.4/go.mod h1:d3CzOMOt0JXGIFZm1StgkyF14EYr3xneR2rNWo7NcMU=
-github.com/kopia/htmluibuild v0.0.1-0.20241001052939-6d8c75cf019a h1:sV6nWaRB5smIQtmRyIX6rKtCPKZ6XvK3RJUG/SjZhOw=
-github.com/kopia/htmluibuild v0.0.1-0.20241001052939-6d8c75cf019a/go.mod h1:h53A5JM3t2qiwxqxusBe+PFgGcgZdS+DWCQvG5PTlto=
+github.com/kopia/htmluibuild v0.0.1-0.20241006020113-c37037c013ee h1:TtJGE2mxkn0rmuIdfsp0hYnJI3SgP0JvdcJOcgLZafw=
+github.com/kopia/htmluibuild v0.0.1-0.20241006020113-c37037c013ee/go.mod h1:h53A5JM3t2qiwxqxusBe+PFgGcgZdS+DWCQvG5PTlto=
 github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
diff --git a/internal/acl/acl.go b/internal/acl/acl.go
index 38288625..4b709cd2 100644
--- a/internal/acl/acl.go
+++ b/internal/acl/acl.go
@@ -73,7 +73,7 @@ type Entry struct {
 
 func nonEmptyString(v string) error {
 	if v == "" {
-		return errors.Errorf("must be non-empty")
+		return errors.New("must be non-empty")
 	}
 
 	return nil
@@ -119,12 +119,12 @@ func oneOf(allowed ...string) valueValidatorFunc {
 // Validate validates entry.
 func (e *Entry) Validate() error {
 	if e == nil {
-		return errors.Errorf("nil acl")
+		return errors.New("nil acl")
 	}
 
 	parts := strings.Split(e.User, "@")
 	if len(parts) != 2 { //nolint:mnd
-		return errors.Errorf("user must be 'username@hostname' possibly including wildcards")
+		return errors.New("user must be 'username@hostname' possibly including wildcards")
 	}
 
 	typ := e.Target[manifest.TypeLabelKey]
@@ -153,7 +153,7 @@ func (e *Entry) Validate() error {
 	}
 
 	if accessLevelToString[e.Access] == "" {
-		return errors.Errorf("valid access level must be specified")
+		return errors.New("valid access level must be specified")
 	}
 
 	return nil
diff --git a/internal/apiclient/apiclient.go b/internal/apiclient/apiclient.go
index 6a5c4adc..b2eb07a9 100644
--- a/internal/apiclient/apiclient.go
+++ b/internal/apiclient/apiclient.go
@@ -73,7 +73,7 @@ func (c *KopiaAPIClient) FetchCSRFTokenForTesting(ctx context.Context) error {
 
 	match := re.FindSubmatch(b)
 	if match == nil {
-		return errors.Errorf("CSRF token not found")
+		return errors.New("CSRF token not found")
 	}
 
 	c.CSRFToken = string(match[1])
diff --git a/internal/bigmap/bigmap_internal.go b/internal/bigmap/bigmap_internal.go
index 06ad26a3..f80e2c43 100644
--- a/internal/bigmap/bigmap_internal.go
+++ b/internal/bigmap/bigmap_internal.go
@@ -435,7 +435,7 @@ func newInternalMapWithOptions(ctx context.Context, hasValues bool, opts *Option
 	tablewSizeIndex := opts.InitialSizeLogarithm - minSizeLogarithm
 
 	if tablewSizeIndex < 1 {
-		return nil, errors.Errorf("invalid initial size")
+		return nil, errors.New("invalid initial size")
 	}
 
 	m := &internalMap{
diff --git a/internal/cache/cache_storage.go b/internal/cache/cache_storage.go
index 7affe3b2..d037f397 100644
--- a/internal/cache/cache_storage.go
+++ b/internal/cache/cache_storage.go
@@ -8,7 +8,6 @@
 
 	"github.com/pkg/errors"
 
-	"github.com/kopia/kopia/internal/ctxutil"
 	"github.com/kopia/kopia/internal/ospath"
 	"github.com/kopia/kopia/repo/blob"
 	"github.com/kopia/kopia/repo/blob/filesystem"
@@ -45,7 +44,7 @@ func NewStorageOrNil(ctx context.Context, cacheDir string, maxBytes int64, subdi
 		}
 	}
 
-	fs, err := filesystem.New(ctxutil.Detach(ctx), &filesystem.Options{
+	fs, err := filesystem.New(context.WithoutCancel(ctx), &filesystem.Options{
 		Path: contentCacheDir,
 		Options: sharded.Options{
 			DirectoryShards: []int{2},
diff --git a/internal/ctxutil/detach.go b/internal/ctxutil/detach.go
deleted file mode 100644
index 8393566e..00000000
--- a/internal/ctxutil/detach.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Package ctxutil implements utilities for manipulating context.
-package ctxutil
-
-import (
-	"context"
-)
-
-type detachedContext struct {
-	// inherit most methods from context.Background()
-	context.Context                 //nolint:containedctx
-	wrapped         context.Context //nolint:containedctx
-}
-
-// Detach returns a context that inheris provided context's values but not deadline or cancellation.
-func Detach(ctx context.Context) context.Context {
-	return detachedContext{context.Background(), ctx}
-}
-
-// GoDetached invokes the provided function in a goroutine where the context is detached.
-func GoDetached(ctx context.Context, fun func(ctx context.Context)) {
-	go func() {
-		fun(Detach(ctx))
-	}()
-}
-
-func (d detachedContext) Value(key interface{}) interface{} {
-	return d.wrapped.Value(key)
-}
diff --git a/internal/epoch/epoch_manager.go b/internal/epoch/epoch_manager.go
index 0a9f16ea..554e6264 100644
--- a/internal/epoch/epoch_manager.go
+++ b/internal/epoch/epoch_manager.go
@@ -35,7 +35,7 @@ type ParametersProvider interface {
 
 // ErrVerySlowIndexWrite is returned by WriteIndex if a write takes more than 2 epochs (usually >48h).
 // This is theoretically possible with laptops going to sleep, etc.
-var ErrVerySlowIndexWrite = errors.Errorf("extremely slow index write - index write took more than two epochs")
+var ErrVerySlowIndexWrite = errors.New("extremely slow index write - index write took more than two epochs")
 
 // Parameters encapsulates all parameters that influence the behavior of epoch manager.
 //
@@ -451,7 +451,7 @@ func (e *Manager) refreshLocked(ctx context.Context) error {
 	nextDelayTime := initiaRefreshAttemptSleep
 
 	if !p.Enabled {
-		return errors.Errorf("epoch manager not enabled")
+		return errors.New("epoch manager not enabled")
 	}
 
 	for err := e.refreshAttemptLocked(ctx); err != nil; err = e.refreshAttemptLocked(ctx) {
@@ -775,7 +775,7 @@ func (e *Manager) GetCompleteIndexSet(ctx context.Context, maxEpoch int) ([]blob
 	}
 }
 
-var errWriteIndexTryAgain = errors.Errorf("try again")
+var errWriteIndexTryAgain = errors.New("try again")
 
 // WriteIndex writes new index blob by picking the appropriate prefix based on current epoch.
 func (e *Manager) WriteIndex(ctx context.Context, dataShards map[blob.ID]blob.Bytes) ([]blob.Metadata, error) {
@@ -1015,7 +1015,7 @@ func (e *Manager) generateRangeCheckpointFromCommittedState(ctx context.Context,
 	}
 
 	if e.timeFunc().After(cs.ValidUntil) {
-		return errors.Errorf("not generating full checkpoint - the committed state is no longer valid")
+		return errors.New("not generating full checkpoint - the committed state is no longer valid")
 	}
 
 	if err := e.compact(ctx, blob.IDsFromMetadata(completeSet), rangeCheckpointBlobPrefix(minEpoch, maxEpoch)); err != nil {
diff --git a/internal/gather/gather_bytes.go b/internal/gather/gather_bytes.go
index 65b175be..178b5955 100644
--- a/internal/gather/gather_bytes.go
+++ b/internal/gather/gather_bytes.go
@@ -14,7 +14,7 @@
 	//nolint:gochecknoglobals
 	invalidSliceBuf = []byte(uuid.NewString())
 	// ErrInvalidOffset checkable error for supplying an invalid offset.
-	ErrInvalidOffset = errors.Errorf("invalid offset")
+	ErrInvalidOffset = errors.New("invalid offset")
 )
 
 // Bytes represents a sequence of bytes split into slices.
@@ -42,7 +42,7 @@ func (b *Bytes) AppendSectionTo(w io.Writer, offset, size int) error {
 	b.assertValid()
 
 	if offset < 0 {
-		return errors.Errorf("invalid offset")
+		return errors.New("invalid offset")
 	}
 
 	// find the index of starting slice
@@ -237,7 +237,7 @@ func (b *bytesReadSeekCloser) Seek(offset int64, whence int) (int64, error) {
 	}
 
 	if newOffset < 0 || newOffset > b.b.Length() {
-		return 0, errors.Errorf("invalid seek")
+		return 0, errors.New("invalid seek")
 	}
 
 	b.offset = newOffset
diff --git a/internal/mount/mount_net_use.go b/internal/mount/mount_net_use.go
index 983cd78f..83374b58 100644
--- a/internal/mount/mount_net_use.go
+++ b/internal/mount/mount_net_use.go
@@ -17,7 +17,7 @@
 // Directory mounts a given directory under a provided drive letter.
 func Directory(ctx context.Context, entry fs.Directory, driveLetter string, _ Options) (Controller, error) {
 	if !isValidWindowsDriveOrAsterisk(driveLetter) {
-		return nil, errors.Errorf("must be a valid drive letter or asterisk")
+		return nil, errors.New("must be a valid drive letter or asterisk")
 	}
 
 	c, err := DirectoryWebDAV(ctx, entry)
diff --git a/internal/mount/mount_unsupported.go b/internal/mount/mount_unsupported.go
index 5596fa05..cc4fb24f 100644
--- a/internal/mount/mount_unsupported.go
+++ b/internal/mount/mount_unsupported.go
@@ -15,5 +15,5 @@
 //
 //nolint:revive
 func Directory(ctx context.Context, entry fs.Directory, mountPoint string, mountOptions Options) (Controller, error) {
-	return nil, errors.Errorf("mounting is not supported")
+	return nil, errors.New("mounting is not supported")
 }
diff --git a/internal/passwordpersist/passwordpersist.go b/internal/passwordpersist/passwordpersist.go
index f7eed3e4..451043d7 100644
--- a/internal/passwordpersist/passwordpersist.go
+++ b/internal/passwordpersist/passwordpersist.go
@@ -10,10 +10,10 @@
 )
 
 // ErrPasswordNotFound is returned when a password cannot be found in a persistent storage.
-var ErrPasswordNotFound = errors.Errorf("password not found")
+var ErrPasswordNotFound = errors.New("password not found")
 
 // ErrUnsupported is returned when a password storage is not supported.
-var ErrUnsupported = errors.Errorf("password storage not supported")
+var ErrUnsupported = errors.New("password storage not supported")
 
 var log = logging.Module("passwordpersist")
 
diff --git a/internal/scheduler/scheduler.go b/internal/scheduler/scheduler.go
index b2b82397..ed03fd5a 100644
--- a/internal/scheduler/scheduler.go
+++ b/internal/scheduler/scheduler.go
@@ -10,7 +10,6 @@
 	"time"
 
 	"github.com/kopia/kopia/internal/clock"
-	"github.com/kopia/kopia/internal/ctxutil"
 	"github.com/kopia/kopia/repo/logging"
 )
 
@@ -66,7 +65,7 @@ func Start(ctx context.Context, getItems GetItemsFunc, opts Options) *Scheduler
 	go func() {
 		defer s.wg.Done()
 
-		s.run(ctxutil.Detach(ctx))
+		s.run(context.WithoutCancel(ctx))
 	}()
 
 	return s
diff --git a/internal/server/api_error.go b/internal/server/api_error.go
index 6152624a..d6345207 100644
--- a/internal/server/api_error.go
+++ b/internal/server/api_error.go
@@ -32,7 +32,7 @@ func accessDeniedError() *apiError {
 }
 
 func repositoryNotWritableError() *apiError {
-	return internalServerError(errors.Errorf("repository is not writable"))
+	return internalServerError(errors.New("repository is not writable"))
 }
 
 func internalServerError(err error) *apiError {
diff --git a/internal/server/api_estimate.go b/internal/server/api_estimate.go
index 8b529a78..bdd0339e 100644
--- a/internal/server/api_estimate.go
+++ b/internal/server/api_estimate.go
@@ -147,7 +147,7 @@ func handleEstimate(ctx context.Context, rc requestContext) (interface{}, *apiEr
 
 	task, ok := rc.srv.taskManager().GetTask(taskID)
 	if !ok {
-		return nil, internalServerError(errors.Errorf("task not found"))
+		return nil, internalServerError(errors.New("task not found"))
 	}
 
 	return task, nil
diff --git a/internal/server/api_restore.go b/internal/server/api_restore.go
index 18f7c015..a31d1427 100644
--- a/internal/server/api_restore.go
+++ b/internal/server/api_restore.go
@@ -118,7 +118,7 @@ func handleRestore(ctx context.Context, rc requestContext) (interface{}, *apiErr
 
 	task, ok := rc.srv.taskManager().GetTask(taskID)
 	if !ok {
-		return nil, internalServerError(errors.Errorf("task not found"))
+		return nil, internalServerError(errors.New("task not found"))
 	}
 
 	return task, nil
diff --git a/internal/server/api_snapshots.go b/internal/server/api_snapshots.go
index c0162555..39c3e824 100644
--- a/internal/server/api_snapshots.go
+++ b/internal/server/api_snapshots.go
@@ -93,7 +93,7 @@ func handleDeleteSnapshots(ctx context.Context, rc requestContext) (interface{},
 
 			for _, sn := range snaps {
 				if sn.Source != req.SourceInfo {
-					return errors.Errorf("source info does not match snapshot source")
+					return errors.New("source info does not match snapshot source")
 				}
 			}
 
diff --git a/internal/server/grpc_session.go b/internal/server/grpc_session.go
index 8cf8496d..9a3102b5 100644
--- a/internal/server/grpc_session.go
+++ b/internal/server/grpc_session.go
@@ -186,10 +186,10 @@ func handleSessionRequest(ctx context.Context, dw repo.DirectRepositoryWriter, a
 		respond(handleApplyRetentionPolicyRequest(ctx, dw, authz, usernameAtHostname, inner.ApplyRetentionPolicy))
 
 	case *grpcapi.SessionRequest_InitializeSession:
-		respond(errorResponse(errors.Errorf("InitializeSession must be the first request in a session")))
+		respond(errorResponse(errors.New("InitializeSession must be the first request in a session")))
 
 	default:
-		respond(errorResponse(errors.Errorf("unhandled session request")))
+		respond(errorResponse(errors.New("unhandled session request")))
 	}
 }
 
@@ -546,7 +546,7 @@ func (s *Server) handleInitialSessionHandshake(srv grpcapi.KopiaRepository_Sessi
 
 	ir := initializeReq.GetInitializeSession()
 	if ir == nil {
-		return repo.WriteSessionOptions{}, errors.Errorf("missing initialization request")
+		return repo.WriteSessionOptions{}, errors.New("missing initialization request")
 	}
 
 	scc := dr.ContentReader().SupportsContentCompression()
diff --git a/internal/server/server.go b/internal/server/server.go
index d80f03b1..7d2e6d5a 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -21,7 +21,6 @@
 
 	"github.com/kopia/kopia/internal/auth"
 	"github.com/kopia/kopia/internal/clock"
-	"github.com/kopia/kopia/internal/ctxutil"
 	"github.com/kopia/kopia/internal/mount"
 	"github.com/kopia/kopia/internal/passwordpersist"
 	"github.com/kopia/kopia/internal/scheduler"
@@ -362,7 +361,7 @@ func (s *Server) handleRequestPossiblyNotConnected(isAuthorized isAuthorizedFunc
 		// process the request while ignoring the cancellation signal
 		// to ensure all goroutines started by it won't be canceled
 		// when the request finishes.
-		ctx = ctxutil.Detach(ctx)
+		ctx = context.WithoutCancel(ctx)
 
 		if isAuthorized(ctx, rc) {
 			v, err = f(ctx, rc)
@@ -585,7 +584,7 @@ func (s *Server) SetRepository(ctx context.Context, rep repo.Repository) error {
 		s.maint = nil
 	}
 
-	s.sched = scheduler.Start(ctxutil.Detach(ctx), s.getSchedulerItems, scheduler.Options{
+	s.sched = scheduler.Start(context.WithoutCancel(ctx), s.getSchedulerItems, scheduler.Options{
 		TimeNow:        clock.Now,
 		Debug:          s.options.DebugScheduler,
 		RefreshChannel: s.schedulerRefresh,
@@ -848,7 +847,7 @@ func (s *Server) InitRepositoryAsync(ctx context.Context, mode string, initializ
 
 		if cctx.Err() != nil {
 			// context canceled
-			return errors.Errorf("operation has been canceled")
+			return errors.New("operation has been canceled")
 		}
 
 		if err != nil {
@@ -1044,11 +1043,11 @@ func (s *Server) refreshScheduler(reason string) {
 // The server will manage sources for a given username@hostname.
 func New(ctx context.Context, options *Options) (*Server, error) {
 	if options.Authorizer == nil {
-		return nil, errors.Errorf("missing authorizer")
+		return nil, errors.New("missing authorizer")
 	}
 
 	if options.PasswordPersist == nil {
-		return nil, errors.Errorf("missing password persistence")
+		return nil, errors.New("missing password persistence")
 	}
 
 	if options.AuthCookieSigningKey == "" {
diff --git a/internal/server/source_manager.go b/internal/server/source_manager.go
index fec1907d..ec0dfbfd 100644
--- a/internal/server/source_manager.go
+++ b/internal/server/source_manager.go
@@ -11,7 +11,6 @@
 	"github.com/kopia/kopia/fs"
 	"github.com/kopia/kopia/fs/localfs"
 	"github.com/kopia/kopia/internal/clock"
-	"github.com/kopia/kopia/internal/ctxutil"
 	"github.com/kopia/kopia/internal/serverapi"
 	"github.com/kopia/kopia/internal/uitask"
 	"github.com/kopia/kopia/repo"
@@ -159,7 +158,7 @@ func (s *sourceManager) start(ctx context.Context, isLocal bool) {
 
 func (s *sourceManager) run(ctx context.Context, isLocal bool) {
 	// make sure we run in a detached context, which ignores outside cancellation and deadline.
-	ctx = ctxutil.Detach(ctx)
+	ctx = context.WithoutCancel(ctx)
 
 	s.setStatus("INITIALIZING")
 	defer s.setStatus("STOPPED")
diff --git a/internal/user/user_manager.go b/internal/user/user_manager.go
index f7d70d98..a51b44d4 100644
--- a/internal/user/user_manager.go
+++ b/internal/user/user_manager.go
@@ -135,11 +135,11 @@ func GetNewProfile(ctx context.Context, r repo.Repository, username string) (*Pr
 // ValidateUsername returns an error if the given username is invalid.
 func ValidateUsername(name string) error {
 	if name == "" {
-		return errors.Errorf("username is required")
+		return errors.New("username is required")
 	}
 
 	if !validUsernameRegexp.MatchString(name) {
-		return errors.Errorf("username must be specified as lowercase 'user@hostname'")
+		return errors.New("username must be specified as lowercase 'user@hostname'")
 	}
 
 	return nil
@@ -167,7 +167,7 @@ func SetUserProfile(ctx context.Context, w repo.RepositoryWriter, p *Profile) er
 // DeleteUserProfile removes user profile with a given username.
 func DeleteUserProfile(ctx context.Context, w repo.RepositoryWriter, username string) error {
 	if username == "" {
-		return errors.Errorf("username is required")
+		return errors.New("username is required")
 	}
 
 	manifests, err := w.FindManifests(ctx, map[string]string{
diff --git a/repo/blob/azure/azure_storage.go b/repo/blob/azure/azure_storage.go
index 808c7b2f..42777975 100644
--- a/repo/blob/azure/azure_storage.go
+++ b/repo/blob/azure/azure_storage.go
@@ -404,7 +404,7 @@ func New(ctx context.Context, opt *Options, isCreate bool) (blob.Storage, error)
 		service, serviceErr = azblob.NewClient(fmt.Sprintf("https://%s/", storageHostname), cred, nil)
 
 	default:
-		return nil, errors.Errorf("one of the storage key, SAS token or client secret must be provided")
+		return nil, errors.New("one of the storage key, SAS token or client secret must be provided")
 	}
 
 	if serviceErr != nil {
diff --git a/repo/blob/azure/azure_versioned.go b/repo/blob/azure/azure_versioned.go
index b0f020d7..fefca26b 100644
--- a/repo/blob/azure/azure_versioned.go
+++ b/repo/blob/azure/azure_versioned.go
@@ -22,7 +22,7 @@ type versionMetadata struct {
 
 func (az *azPointInTimeStorage) getVersionedBlobMeta(it *azblobmodels.BlobItem) (*versionMetadata, error) {
 	if it.VersionID == nil {
-		return nil, errors.Errorf("versionID is nil. Versioning must be enabled on the container for PIT")
+		return nil, errors.New("versionID is nil. Versioning must be enabled on the container for PIT")
 	}
 
 	bm := az.getBlobMeta(it)
diff --git a/repo/blob/filesystem/filesystem_storage.go b/repo/blob/filesystem/filesystem_storage.go
index a6841cbf..ed256157 100644
--- a/repo/blob/filesystem/filesystem_storage.go
+++ b/repo/blob/filesystem/filesystem_storage.go
@@ -43,7 +43,7 @@ type fsImpl struct {
 	osi osInterface
 }
 
-var errRetriableInvalidLength = errors.Errorf("invalid length (retriable)")
+var errRetriableInvalidLength = errors.New("invalid length (retriable)")
 
 func (fs *fsImpl) isRetriable(err error) bool {
 	if err == nil {
@@ -115,7 +115,7 @@ func (fs *fsImpl) GetBlobFromPath(ctx context.Context, dirPath, path string, off
 				}
 			}
 
-			return errors.Errorf("invalid length")
+			return errors.New("invalid length")
 		}
 
 		return nil
diff --git a/repo/blob/rclone/rclone_storage.go b/repo/blob/rclone/rclone_storage.go
index 4cb48398..72478f7f 100644
--- a/repo/blob/rclone/rclone_storage.go
+++ b/repo/blob/rclone/rclone_storage.go
@@ -240,7 +240,7 @@ func (r *rcloneStorage) runRCloneAndWaitForServerAddress(ctx context.Context, c
 		return rcloneURLs{}, err
 
 	case <-time.After(startupTimeout):
-		return rcloneURLs{}, errors.Errorf("timed out waiting for rclone to start")
+		return rcloneURLs{}, errors.New("timed out waiting for rclone to start")
 	}
 }
 
diff --git a/repo/blob/readonly/readonly_storage.go b/repo/blob/readonly/readonly_storage.go
index 5d01d963..1e1ac76b 100644
--- a/repo/blob/readonly/readonly_storage.go
+++ b/repo/blob/readonly/readonly_storage.go
@@ -10,7 +10,7 @@
 )
 
 // ErrReadonly returns an error indicating that storage is read only.
-var ErrReadonly = errors.Errorf("storage is read-only")
+var ErrReadonly = errors.New("storage is read-only")
 
 // readonlyStorage prevents all mutations on the underlying storage.
 type readonlyStorage struct {
diff --git a/repo/blob/s3/s3_storage.go b/repo/blob/s3/s3_storage.go
index 08fb3726..fcfb2440 100644
--- a/repo/blob/s3/s3_storage.go
+++ b/repo/blob/s3/s3_storage.go
@@ -314,7 +314,7 @@ func getCustomTransport(opt *Options) (*http.Transport, error) {
 		rootcas := x509.NewCertPool()
 
 		if ok := rootcas.AppendCertsFromPEM(opt.RootCA); !ok {
-			return nil, errors.Errorf("cannot parse provided CA")
+			return nil, errors.New("cannot parse provided CA")
 		}
 
 		transport.TLSClientConfig.RootCAs = rootcas
diff --git a/repo/blob/sftp/sftp_storage.go b/repo/blob/sftp/sftp_storage.go
index c6c0f30d..2683ef6e 100644
--- a/repo/blob/sftp/sftp_storage.go
+++ b/repo/blob/sftp/sftp_storage.go
@@ -379,7 +379,7 @@ func getHostKeyCallback(opt *Options) (ssh.HostKeyCallback, error) {
 	}
 
 	if f := opt.knownHostsFile(); !ospath.IsAbs(f) {
-		return nil, errors.Errorf("known hosts path must be absolute")
+		return nil, errors.New("known hosts path must be absolute")
 	}
 
 	//nolint:wrapcheck
@@ -400,7 +400,7 @@ func getSigner(opt *Options) (ssh.Signer, error) {
 		var err error
 
 		if f := opt.Keyfile; !ospath.IsAbs(f) {
-			return nil, errors.Errorf("key file path must be absolute")
+			return nil, errors.New("key file path must be absolute")
 		}
 
 		privateKeyData, err = os.ReadFile(opt.Keyfile)
diff --git a/repo/blob/storage.go b/repo/blob/storage.go
index 6d8cf029..f0481d06 100644
--- a/repo/blob/storage.go
+++ b/repo/blob/storage.go
@@ -17,10 +17,10 @@
 var log = logging.Module("blob")
 
 // ErrSetTimeUnsupported is returned by implementations of Storage that don't support SetTime.
-var ErrSetTimeUnsupported = errors.Errorf("SetTime is not supported")
+var ErrSetTimeUnsupported = errors.New("SetTime is not supported")
 
 // ErrInvalidRange is returned when the requested blob offset or length is invalid.
-var ErrInvalidRange = errors.Errorf("invalid blob offset or length")
+var ErrInvalidRange = errors.New("invalid blob offset or length")
 
 // InvalidCredentialsErrStr is the error string returned by the provider
 // when a token has expired.
diff --git a/repo/blob/throttling/throttling_semaphore.go b/repo/blob/throttling/throttling_semaphore.go
index 36faf09a..1a490d19 100644
--- a/repo/blob/throttling/throttling_semaphore.go
+++ b/repo/blob/throttling/throttling_semaphore.go
@@ -46,7 +46,7 @@ func (s *semaphore) SetLimit(limit int) error {
 	defer s.mu.Unlock()
 
 	if limit < 0 {
-		return errors.Errorf("invalid limit")
+		return errors.New("invalid limit")
 	}
 
 	if limit > 0 {
diff --git a/repo/blob/throttling/token_bucket.go b/repo/blob/throttling/token_bucket.go
index fd70c3c1..47aee1e2 100644
--- a/repo/blob/throttling/token_bucket.go
+++ b/repo/blob/throttling/token_bucket.go
@@ -87,7 +87,7 @@ func (b *tokenBucket) SetLimit(maxTokens float64) error {
 	defer b.mu.Unlock()
 
 	if maxTokens < 0 {
-		return errors.Errorf("limit cannot be negative")
+		return errors.New("limit cannot be negative")
 	}
 
 	b.maxTokens = maxTokens
diff --git a/repo/connect.go b/repo/connect.go
index ec29efad..b1cef53f 100644
--- a/repo/connect.go
+++ b/repo/connect.go
@@ -22,7 +22,7 @@ type ConnectOptions struct {
 
 // ErrRepositoryNotInitialized is returned when attempting to connect to repository that has not
 // been initialized.
-var ErrRepositoryNotInitialized = errors.Errorf("repository not initialized in the provided storage")
+var ErrRepositoryNotInitialized = errors.New("repository not initialized in the provided storage")
 
 // Connect connects to the repository in the specified storage and persists the configuration and credentials in the file provided.
 func Connect(ctx context.Context, configFile string, st blob.Storage, password string, opt *ConnectOptions) error {
@@ -89,7 +89,7 @@ func Disconnect(ctx context.Context, configFile string) error {
 
 	if cfg.Caching != nil && cfg.Caching.CacheDirectory != "" {
 		if !ospath.IsAbs(cfg.Caching.CacheDirectory) {
-			return errors.Errorf("cache directory was not absolute, refusing to delete")
+			return errors.New("cache directory was not absolute, refusing to delete")
 		}
 
 		if err = os.RemoveAll(cfg.Caching.CacheDirectory); err != nil {
diff --git a/repo/content/committed_content_index_disk_cache.go b/repo/content/committed_content_index_disk_cache.go
index 6a8fc211..0ea6fdff 100644
--- a/repo/content/committed_content_index_disk_cache.go
+++ b/repo/content/committed_content_index_disk_cache.go
@@ -159,7 +159,7 @@ func writeTempFileAtomic(dirname string, data []byte) (string, error) {
 	}
 
 	if err := tf.Close(); err != nil {
-		return "", errors.Errorf("can't close tmp file")
+		return "", errors.New("can't close tmp file")
 	}
 
 	return tf.Name(), nil
diff --git a/repo/content/content_manager_lock_free.go b/repo/content/content_manager_lock_free.go
index d43978e0..c070f0fd 100644
--- a/repo/content/content_manager_lock_free.go
+++ b/repo/content/content_manager_lock_free.go
@@ -39,7 +39,7 @@ func (sm *SharedManager) maybeCompressAndEncryptDataForPacking(data gather.Bytes
 	//nolint:nestif
 	if comp != NoCompression {
 		if mp.IndexVersion < index.Version2 {
-			return NoCompression, errors.Errorf("compression is not enabled for this repository")
+			return NoCompression, errors.New("compression is not enabled for this repository")
 		}
 
 		var tmp gather.WriteBuffer
diff --git a/repo/content/index/id.go b/repo/content/index/id.go
index e57e046e..062de0ee 100644
--- a/repo/content/index/id.go
+++ b/repo/content/index/id.go
@@ -26,7 +26,7 @@ func (p IDPrefix) ValidateSingle() error {
 		}
 	}
 
-	return errors.Errorf("invalid prefix, must be empty or a single letter between 'g' and 'z'")
+	return errors.New("invalid prefix, must be empty or a single letter between 'g' and 'z'")
 }
 
 // ID is an identifier of content in content-addressable storage.
@@ -158,11 +158,11 @@ func IDFromHash(prefix IDPrefix, hash []byte) (ID, error) {
 	var id ID
 
 	if len(hash) > len(id.data) {
-		return EmptyID, errors.Errorf("hash too long")
+		return EmptyID, errors.New("hash too long")
 	}
 
 	if len(hash) == 0 {
-		return EmptyID, errors.Errorf("hash too short")
+		return EmptyID, errors.New("hash too short")
 	}
 
 	if err := prefix.ValidateSingle(); err != nil {
@@ -193,14 +193,14 @@ func ParseID(s string) (ID, error) {
 		id.prefix = s[0]
 
 		if id.prefix < 'g' || id.prefix > 'z' {
-			return id, errors.Errorf("invalid content prefix")
+			return id, errors.New("invalid content prefix")
 		}
 
 		s = s[1:]
 	}
 
 	if len(s) > 2*len(id.data) {
-		return id, errors.Errorf("hash too long")
+		return id, errors.New("hash too long")
 	}
 
 	n, err := hex.Decode(id.data[:], []byte(s))
diff --git a/repo/content/index/index_builder.go b/repo/content/index/index_builder.go
index afabcd75..05f54482 100644
--- a/repo/content/index/index_builder.go
+++ b/repo/content/index/index_builder.go
@@ -185,7 +185,7 @@ func (b Builder) shard(maxShardSize int) []Builder {
 // Returns shard bytes and function to clean up after the shards have been written.
 func (b Builder) BuildShards(indexVersion int, stable bool, shardSize int) ([]gather.Bytes, func(), error) {
 	if shardSize == 0 {
-		return nil, nil, errors.Errorf("invalid shard size")
+		return nil, nil, errors.New("invalid shard size")
 	}
 
 	var (
diff --git a/repo/content/index/index_v1.go b/repo/content/index/index_v1.go
index ba0e7ca8..cae8bfd1 100644
--- a/repo/content/index/index_v1.go
+++ b/repo/content/index/index_v1.go
@@ -340,11 +340,11 @@ func (b *indexBuilderV1) writeEntry(w io.Writer, it Info, entry []byte) error {
 	}
 
 	if it.CompressionHeaderID != 0 {
-		return errors.Errorf("compression not supported in index v1")
+		return errors.New("compression not supported in index v1")
 	}
 
 	if it.EncryptionKeyID != 0 {
-		return errors.Errorf("encryption key ID not supported in index v1")
+		return errors.New("encryption key ID not supported in index v1")
 	}
 
 	if err := b.formatEntry(entry, it); err != nil {
@@ -411,7 +411,7 @@ func v1ReadHeader(data []byte) (v1HeaderInfo, error) {
 	}
 
 	if hi.keySize <= 1 || hi.valueSize < 0 || hi.entryCount < 0 {
-		return v1HeaderInfo{}, errors.Errorf("invalid header")
+		return v1HeaderInfo{}, errors.New("invalid header")
 	}
 
 	return hi, nil
diff --git a/repo/content/index/index_v2.go b/repo/content/index/index_v2.go
index fe6c72c3..10e34ece 100644
--- a/repo/content/index/index_v2.go
+++ b/repo/content/index/index_v2.go
@@ -697,12 +697,12 @@ func openV2PackIndex(data []byte, closer func() error) (Index, error) {
 	}
 
 	if hi.keySize <= 1 || hi.entrySize < v2EntryMinLength || hi.entrySize > v2EntryMaxLength || hi.entryCount < 0 || hi.formatCount > v2MaxFormatCount {
-		return nil, errors.Errorf("invalid header")
+		return nil, errors.New("invalid header")
 	}
 
 	hi.entryStride = int64(hi.keySize + hi.entrySize)
 	if hi.entryStride > v2MaxEntrySize {
-		return nil, errors.Errorf("invalid header - entry stride too big")
+		return nil, errors.New("invalid header - entry stride too big")
 	}
 
 	hi.entriesOffset = v2IndexHeaderSize
@@ -712,7 +712,7 @@ func openV2PackIndex(data []byte, closer func() error) (Index, error) {
 	// pre-read formats section
 	formatsBuf, err := safeSlice(data, hi.formatsOffset, int(hi.formatCount)*v2FormatInfoSize)
 	if err != nil {
-		return nil, errors.Errorf("unable to read formats section")
+		return nil, errors.New("unable to read formats section")
 	}
 
 	packIDs := make([]blob.ID, hi.packCount)
@@ -720,7 +720,7 @@ func openV2PackIndex(data []byte, closer func() error) (Index, error) {
 	for i := range int(hi.packCount) { //nolint:gosec
 		buf, err := safeSlice(data, hi.packsOffset+int64(v2PackInfoSize*i), v2PackInfoSize)
 		if err != nil {
-			return nil, errors.Errorf("unable to read pack blob IDs section - 1")
+			return nil, errors.New("unable to read pack blob IDs section - 1")
 		}
 
 		nameLength := int(buf[0])
@@ -728,7 +728,7 @@ func openV2PackIndex(data []byte, closer func() error) (Index, error) {
 
 		nameBuf, err := safeSliceString(data, int64(nameOffset), nameLength)
 		if err != nil {
-			return nil, errors.Errorf("unable to read pack blob IDs section - 2")
+			return nil, errors.New("unable to read pack blob IDs section - 2")
 		}
 
 		packIDs[i] = blob.ID(nameBuf)
diff --git a/repo/format/blobcfg_blob.go b/repo/format/blobcfg_blob.go
index 31833513..54a95ca6 100644
--- a/repo/format/blobcfg_blob.go
+++ b/repo/format/blobcfg_blob.go
@@ -31,11 +31,11 @@ func (r *BlobStorageConfiguration) IsRetentionEnabled() bool {
 // Validate validates the blob config parameters.
 func (r *BlobStorageConfiguration) Validate() error {
 	if (r.RetentionMode == "") != (r.RetentionPeriod == 0) {
-		return errors.Errorf("both retention mode and period must be provided when setting blob retention properties")
+		return errors.New("both retention mode and period must be provided when setting blob retention properties")
 	}
 
 	if r.RetentionPeriod != 0 && r.RetentionPeriod < 24*time.Hour {
-		return errors.Errorf("invalid retention-period, the minimum required is 1-day and there is no maximum limit")
+		return errors.New("invalid retention-period, the minimum required is 1-day and there is no maximum limit")
 	}
 
 	return nil
@@ -78,7 +78,7 @@ func deserializeBlobCfgBytes(j *KopiaRepositoryJSON, encryptedBlobCfgBytes, form
 	case aes256GcmEncryption:
 		plainText, err = decryptRepositoryBlobBytesAes256Gcm(encryptedBlobCfgBytes, formatEncryptionKey, j.UniqueID)
 		if err != nil {
-			return BlobStorageConfiguration{}, errors.Errorf("unable to decrypt repository blobcfg blob")
+			return BlobStorageConfiguration{}, errors.New("unable to decrypt repository blobcfg blob")
 		}
 
 	default:
diff --git a/repo/format/content_format.go b/repo/format/content_format.go
index 11ee9223..fc964a17 100644
--- a/repo/format/content_format.go
+++ b/repo/format/content_format.go
@@ -80,7 +80,7 @@ func (v *MutableParameters) Validate() error {
 	}
 
 	if v.IndexVersion < 0 || v.IndexVersion > index.Version2 {
-		return errors.Errorf("invalid index version, supported versions are 1 & 2")
+		return errors.New("invalid index version, supported versions are 1 & 2")
 	}
 
 	if err := v.EpochParameters.Validate(); err != nil {
diff --git a/repo/format/format_blob.go b/repo/format/format_blob.go
index c17ed0ee..53ae50e3 100644
--- a/repo/format/format_blob.go
+++ b/repo/format/format_blob.go
@@ -31,7 +31,7 @@
 const KopiaRepositoryBlobID = "kopia.repository"
 
 // ErrInvalidPassword is returned when repository password is invalid.
-var ErrInvalidPassword = errors.Errorf("invalid repository password") // +checklocksignore
+var ErrInvalidPassword = errors.New("invalid repository password") // +checklocksignore
 
 //nolint:gochecknoglobals
 var (
diff --git a/repo/format/format_change_password.go b/repo/format/format_change_password.go
index 28927bd7..34875aa1 100644
--- a/repo/format/format_change_password.go
+++ b/repo/format/format_change_password.go
@@ -15,7 +15,7 @@ func (m *Manager) ChangePassword(ctx context.Context, newPassword string) error
 	defer m.mu.Unlock()
 
 	if !m.repoConfig.EnablePasswordChange {
-		return errors.Errorf("password changes are not supported for repositories created using Kopia v0.8 or older")
+		return errors.New("password changes are not supported for repositories created using Kopia v0.8 or older")
 	}
 
 	newFormatEncryptionKey, err := m.j.DeriveFormatEncryptionKeyFromPassword(newPassword)
diff --git a/repo/format/format_manager.go b/repo/format/format_manager.go
index a3a0a325..1f24d6e0 100644
--- a/repo/format/format_manager.go
+++ b/repo/format/format_manager.go
@@ -138,7 +138,7 @@ func (m *Manager) refresh(ctx context.Context) error {
 
 	b, err = addFormatBlobChecksumAndLength(b)
 	if err != nil {
-		return errors.Errorf("unable to add checksum")
+		return errors.New("unable to add checksum")
 	}
 
 	// use old key, if present to avoid deriving it, which is expensive
@@ -309,7 +309,7 @@ func (m *Manager) LoadedTime() time.Time {
 // +checklocks:m.mu
 func (m *Manager) updateRepoConfigLocked(ctx context.Context) error {
 	if err := m.j.EncryptRepositoryConfig(m.repoConfig, m.formatEncryptionKey); err != nil {
-		return errors.Errorf("unable to encrypt format bytes")
+		return errors.New("unable to encrypt format bytes")
 	}
 
 	if err := m.j.WriteKopiaRepositoryBlob(ctx, m.blobs, m.blobCfgBlob); err != nil {
@@ -420,7 +420,7 @@ func NewManagerWithCache(
 }
 
 // ErrAlreadyInitialized indicates that repository has already been initialized.
-var ErrAlreadyInitialized = errors.Errorf("repository already initialized")
+var ErrAlreadyInitialized = errors.New("repository already initialized")
 
 // Initialize initializes the format blob in a given storage.
 func Initialize(ctx context.Context, st blob.Storage, formatBlob *KopiaRepositoryJSON, repoConfig *RepositoryConfig, blobcfg BlobStorageConfiguration, password string) error {
@@ -439,7 +439,7 @@ func Initialize(ctx context.Context, st blob.Storage, formatBlob *KopiaRepositor
 
 	err = st.GetBlob(ctx, KopiaBlobCfgBlobID, 0, -1, &tmp)
 	if err == nil {
-		return errors.Errorf("possible corruption: blobcfg blob exists, but format blob is not found")
+		return errors.New("possible corruption: blobcfg blob exists, but format blob is not found")
 	}
 
 	if !errors.Is(err, blob.ErrBlobNotFound) {
diff --git a/repo/format/format_set_parameters.go b/repo/format/format_set_parameters.go
index 62f33989..b91688a9 100644
--- a/repo/format/format_set_parameters.go
+++ b/repo/format/format_set_parameters.go
@@ -31,7 +31,7 @@ func (m *Manager) SetParameters(
 	m.repoConfig.RequiredFeatures = requiredFeatures
 
 	if err := m.j.EncryptRepositoryConfig(m.repoConfig, m.formatEncryptionKey); err != nil {
-		return errors.Errorf("unable to encrypt format bytes")
+		return errors.New("unable to encrypt format bytes")
 	}
 
 	if err := m.j.WriteBlobCfgBlob(ctx, m.blobs, blobcfg, m.formatEncryptionKey); err != nil {
diff --git a/repo/format/repository_config.go b/repo/format/repository_config.go
index 69d81b30..85164370 100644
--- a/repo/format/repository_config.go
+++ b/repo/format/repository_config.go
@@ -29,7 +29,7 @@ func (f *KopiaRepositoryJSON) decryptRepositoryConfig(masterKey []byte) (*Reposi
 	case aes256GcmEncryption:
 		plainText, err := decryptRepositoryBlobBytesAes256Gcm(f.EncryptedFormatBytes, masterKey, f.UniqueID)
 		if err != nil {
-			return nil, errors.Errorf("unable to decrypt repository format")
+			return nil, errors.New("unable to decrypt repository format")
 		}
 
 		var erc EncryptedRepositoryConfig
diff --git a/repo/grpc_repository_client.go b/repo/grpc_repository_client.go
index e5caa9ca..cf4c27cf 100644
--- a/repo/grpc_repository_client.go
+++ b/repo/grpc_repository_client.go
@@ -18,7 +18,6 @@
 	"google.golang.org/grpc/credentials"
 
 	"github.com/kopia/kopia/internal/clock"
-	"github.com/kopia/kopia/internal/ctxutil"
 	"github.com/kopia/kopia/internal/gather"
 	apipb "github.com/kopia/kopia/internal/grpcapi"
 	"github.com/kopia/kopia/internal/retry"
@@ -722,7 +721,7 @@ func (r *grpcRepositoryClient) WriteContent(ctx context.Context, data gather.Byt
 
 	// we will be writing asynchronously and server will reject this write, fail early.
 	if prefix == manifest.ContentPrefix {
-		return content.EmptyID, errors.Errorf("writing manifest contents not allowed")
+		return content.EmptyID, errors.New("writing manifest contents not allowed")
 	}
 
 	var hashOutput [128]byte
@@ -739,7 +738,7 @@ func (r *grpcRepositoryClient) WriteContent(ctx context.Context, data gather.Byt
 	// clone so that caller can reuse the buffer
 	clone := data.ToByteSlice()
 
-	if err := r.doWriteAsync(ctxutil.Detach(ctx), contentID, clone, prefix, comp); err != nil {
+	if err := r.doWriteAsync(context.WithoutCancel(ctx), contentID, clone, prefix, comp); err != nil {
 		return content.EmptyID, err
 	}
 
@@ -867,7 +866,7 @@ func baseURLToURI(baseURL string) (uri string, err error) {
 	}
 
 	if u.Scheme != "kopia" && u.Scheme != "https" && u.Scheme != "unix+https" {
-		return "", errors.Errorf("invalid server address, must be 'https://host:port' or 'unix+https://<path>")
+		return "", errors.New("invalid server address, must be 'https://host:port' or 'unix+https://<path>")
 	}
 
 	uri = net.JoinHostPort(u.Hostname(), u.Port())
@@ -897,7 +896,7 @@ func (r *grpcRepositoryClient) getOrEstablishInnerSession(ctx context.Context) (
 		r.innerSessionAttemptCount++
 
 		v, err := retry.WithExponentialBackoff(ctx, "establishing session", func() (*grpcInnerSession, error) {
-			sess, err := cli.Session(ctxutil.Detach(ctx))
+			sess, err := cli.Session(context.WithoutCancel(ctx))
 			if err != nil {
 				return nil, errors.Wrap(err, "Session()")
 			}
diff --git a/repo/local_config.go b/repo/local_config.go
index c49580f3..f6567a72 100644
--- a/repo/local_config.go
+++ b/repo/local_config.go
@@ -21,7 +21,7 @@
 const configDirMode = 0o700
 
 // ErrCannotWriteToRepoConnectionWithPermissiveCacheLoading error to indicate.
-var ErrCannotWriteToRepoConnectionWithPermissiveCacheLoading = errors.Errorf("cannot write to repo connection with permissive cache loading")
+var ErrCannotWriteToRepoConnectionWithPermissiveCacheLoading = errors.New("cannot write to repo connection with permissive cache loading")
 
 // ClientOptions contains client-specific options that are persisted in local configuration file.
 type ClientOptions struct {
diff --git a/repo/maintenance/content_rewrite.go b/repo/maintenance/content_rewrite.go
index a7eb196e..3c737a57 100644
--- a/repo/maintenance/content_rewrite.go
+++ b/repo/maintenance/content_rewrite.go
@@ -39,7 +39,7 @@ type contentInfoOrError struct {
 // blobs and index entries to point at them.
 func RewriteContents(ctx context.Context, rep repo.DirectRepositoryWriter, opt *RewriteContentsOptions, safety SafetyParameters) error {
 	if opt == nil {
-		return errors.Errorf("missing options")
+		return errors.New("missing options")
 	}
 
 	if opt.ShortPacks {
diff --git a/repo/maintenance/maintenance_schedule.go b/repo/maintenance/maintenance_schedule.go
index e7398c2a..94336900 100644
--- a/repo/maintenance/maintenance_schedule.go
+++ b/repo/maintenance/maintenance_schedule.go
@@ -135,7 +135,7 @@ func GetSchedule(ctx context.Context, rep repo.DirectRepository) (*Schedule, err
 	v := tmp.ToByteSlice()
 
 	if len(v) < c.NonceSize() {
-		return nil, errors.Errorf("invalid schedule blob")
+		return nil, errors.New("invalid schedule blob")
 	}
 
 	j, err := c.Open(nil, v[0:c.NonceSize()], v[c.NonceSize():], maintenanceScheduleAEADExtraData)
diff --git a/repo/manifest/manifest_manager.go b/repo/manifest/manifest_manager.go
index 8bb2f39f..7e00762f 100644
--- a/repo/manifest/manifest_manager.go
+++ b/repo/manifest/manifest_manager.go
@@ -70,7 +70,7 @@ type Manager struct {
 // Put serializes the provided payload to JSON and persists it. Returns unique identifier that represents the manifest.
 func (m *Manager) Put(ctx context.Context, labels map[string]string, payload interface{}) (ID, error) {
 	if labels[TypeLabelKey] == "" {
-		return "", errors.Errorf("'type' label is required")
+		return "", errors.New("'type' label is required")
 	}
 
 	random := make([]byte, manifestIDLength)
diff --git a/repo/object/object_manager.go b/repo/object/object_manager.go
index 213069b3..15088824 100644
--- a/repo/object/object_manager.go
+++ b/repo/object/object_manager.go
@@ -108,7 +108,7 @@ func (om *Manager) closedWriter(ow *objectWriter) {
 // so this method should only be used for very large files where this overhead is relatively small.
 func (om *Manager) Concatenate(ctx context.Context, objectIDs []ID) (ID, error) {
 	if len(objectIDs) == 0 {
-		return EmptyID, errors.Errorf("empty list of objects")
+		return EmptyID, errors.New("empty list of objects")
 	}
 
 	if len(objectIDs) == 1 {
diff --git a/repo/object/objectid.go b/repo/object/objectid.go
index 3f934d1d..c306c7f2 100644
--- a/repo/object/objectid.go
+++ b/repo/object/objectid.go
@@ -180,7 +180,7 @@ func ParseID(s string) (ID, error) {
 	}
 
 	if id.indirection > 0 && id.compression {
-		return id, errors.Errorf("malformed object ID - compression and indirection are mutually exclusive")
+		return id, errors.New("malformed object ID - compression and indirection are mutually exclusive")
 	}
 
 	cid, err := index.ParseID(s)
diff --git a/repo/open.go b/repo/open.go
index 2c55e800..52dbac0c 100644
--- a/repo/open.go
+++ b/repo/open.go
@@ -86,7 +86,7 @@ type Options struct {
 
 // ErrRepositoryUnavailableDueToUpgradeInProgress is returned when repository
 // is undergoing upgrade that requires exclusive access.
-var ErrRepositoryUnavailableDueToUpgradeInProgress = errors.Errorf("repository upgrade in progress")
+var ErrRepositoryUnavailableDueToUpgradeInProgress = errors.New("repository upgrade in progress")
 
 // Open opens a Repository specified in the configuration file.
 func Open(ctx context.Context, configFile, password string, options *Options) (rep Repository, err error) {
@@ -203,7 +203,7 @@ func(ctx context.Context) error {
 // openDirect opens the repository that directly manipulates blob storage..
 func openDirect(ctx context.Context, configFile string, lc *LocalConfig, password string, options *Options) (rep Repository, err error) {
 	if lc.Storage == nil {
-		return nil, errors.Errorf("storage not set in the configuration file")
+		return nil, errors.New("storage not set in the configuration file")
 	}
 
 	st, err := blob.NewStorage(ctx, *lc.Storage, false)
diff --git a/snapshot/manager.go b/snapshot/manager.go
index 41e56251..d25c3f91 100644
--- a/snapshot/manager.go
+++ b/snapshot/manager.go
@@ -23,7 +23,7 @@
 )
 
 // ErrSnapshotNotFound is returned when a snapshot is not found.
-var ErrSnapshotNotFound = errors.Errorf("snapshot not found")
+var ErrSnapshotNotFound = errors.New("snapshot not found")
 
 const (
 	typeKey = manifest.TypeLabelKey
@@ -100,7 +100,7 @@ func LoadSnapshot(ctx context.Context, rep repo.Repository, manifestID manifest.
 	}
 
 	if em.Labels[manifest.TypeLabelKey] != ManifestType {
-		return nil, errors.Errorf("manifest is not a snapshot")
+		return nil, errors.New("manifest is not a snapshot")
 	}
 
 	sm.ID = manifestID
diff --git a/snapshot/policy/policy.go b/snapshot/policy/policy.go
index c7c82fbb..e2e0fa53 100644
--- a/snapshot/policy/policy.go
+++ b/snapshot/policy/policy.go
@@ -94,7 +94,7 @@ func ValidatePolicy(si snapshot.SourceInfo, pol *Policy) error {
 // validatePolicyPath validates that the provided policy path is valid and the path exists.
 func validatePolicyPath(p string) error {
 	if isSlashOrBackslash(p[len(p)-1]) && !isRootPath(p) {
-		return errors.Errorf("path cannot end with a slash or a backslash")
+		return errors.New("path cannot end with a slash or a backslash")
 	}
 
 	return nil
diff --git a/snapshot/policy/upload_policy.go b/snapshot/policy/upload_policy.go
index 3019334d..832db142 100644
--- a/snapshot/policy/upload_policy.go
+++ b/snapshot/policy/upload_policy.go
@@ -30,7 +30,7 @@ func (p *UploadPolicy) Merge(src UploadPolicy, def *UploadPolicyDefinition, si s
 // ValidateUploadPolicy returns an error if manual field is set along with Upload fields.
 func ValidateUploadPolicy(si snapshot.SourceInfo, p UploadPolicy) error {
 	if si.Path != "" && p.MaxParallelSnapshots != nil {
-		return errors.Errorf("max parallel snapshots cannot be specified for paths, only global, username@hostname or @hostname")
+		return errors.New("max parallel snapshots cannot be specified for paths, only global, username@hostname or @hostname")
 	}
 
 	return nil
diff --git a/snapshot/restore/local_fs_output.go b/snapshot/restore/local_fs_output.go
index b55bab29..32b356c7 100644
--- a/snapshot/restore/local_fs_output.go
+++ b/snapshot/restore/local_fs_output.go
@@ -222,7 +222,7 @@ func (o *FilesystemOutput) CreateSymlink(ctx context.Context, relativePath strin
 	case fileIsSymlink(st):
 		// Throw error if we are not overwriting symlinks
 		if !o.OverwriteSymlinks {
-			return errors.Errorf("will not overwrite existing symlink")
+			return errors.New("will not overwrite existing symlink")
 		}
 
 		// Remove the existing symlink before symlink creation
diff --git a/snapshot/snapshotfs/dir_reader.go b/snapshot/snapshotfs/dir_reader.go
index 07aa5028..5761b2d9 100644
--- a/snapshot/snapshotfs/dir_reader.go
+++ b/snapshot/snapshotfs/dir_reader.go
@@ -21,7 +21,7 @@ func readDirEntries(r io.Reader) ([]*snapshot.DirEntry, *fs.DirectorySummary, er
 	}
 
 	if dir.StreamType != directoryStreamType {
-		return nil, nil, errors.Errorf("invalid directory stream type")
+		return nil, nil, errors.New("invalid directory stream type")
 	}
 
 	return dir.Entries, dir.Summary, nil
diff --git a/snapshot/snapshotfs/objref.go b/snapshot/snapshotfs/objref.go
index d44b9980..3a84c092 100644
--- a/snapshot/snapshotfs/objref.go
+++ b/snapshot/snapshotfs/objref.go
@@ -69,7 +69,7 @@ func parseNestedObjectID(ctx context.Context, startingDir fs.Entry, parts []stri
 
 	hoid, ok := e.(object.HasObjectID)
 	if !ok {
-		return object.EmptyID, errors.Errorf("entry without ObjectID")
+		return object.EmptyID, errors.New("entry without ObjectID")
 	}
 
 	return hoid.ObjectID(), nil
diff --git a/snapshot/snapshotfs/snapshot_tree_walker.go b/snapshot/snapshotfs/snapshot_tree_walker.go
index b54ad9e1..07adf7c2 100644
--- a/snapshot/snapshotfs/snapshot_tree_walker.go
+++ b/snapshot/snapshotfs/snapshot_tree_walker.go
@@ -150,7 +150,7 @@ func (w *TreeWalker) processDirEntry(ctx context.Context, dir fs.Directory, entr
 // Process processes the snapshot tree entry.
 func (w *TreeWalker) Process(ctx context.Context, e fs.Entry, entryPath string) error {
 	if oidOf(e) == object.EmptyID {
-		return errors.Errorf("entry does not have ObjectID")
+		return errors.New("entry does not have ObjectID")
 	}
 
 	if w.alreadyProcessed(ctx, e) {
diff --git a/snapshot/snapshotfs/upload_actions.go b/snapshot/snapshotfs/upload_actions.go
index 12582079..957245bb 100644
--- a/snapshot/snapshotfs/upload_actions.go
+++ b/snapshot/snapshotfs/upload_actions.go
@@ -127,7 +127,7 @@ func prepareCommandForAction(ctx context.Context, actionType string, h *policy.A
 	default:
 		cancel()
 
-		return nil, nil, errors.Errorf("action did not provide either script nor command to run")
+		return nil, nil, errors.New("action did not provide either script nor command to run")
 	}
 
 	// all actions run inside temporary working directory
diff --git a/snapshot/snapshotgc/gc.go b/snapshot/snapshotgc/gc.go
index 172f4054..0368e4b4 100644
--- a/snapshot/snapshotgc/gc.go
+++ b/snapshot/snapshotgc/gc.go
@@ -89,7 +89,7 @@ func Run(ctx context.Context, rep repo.DirectRepositoryWriter, gcDelete bool, sa
 		l.Infof("GC found %v in-use system-contents (%v)", st.SystemCount, units.BytesString(st.SystemBytes))
 
 		if st.UnusedCount > 0 && !gcDelete {
-			return errors.Errorf("Not deleting because 'gcDelete' was not set")
+			return errors.New("Not deleting because 'gcDelete' was not set")
 		}
 
 		return nil
diff --git a/tools/gettool/autodownload/autodownload.go b/tools/gettool/autodownload/autodownload.go
index f79dccef..9ab7d581 100644
--- a/tools/gettool/autodownload/autodownload.go
+++ b/tools/gettool/autodownload/autodownload.go
@@ -266,7 +266,7 @@ func downloadInternal(url, dir string, checksum map[string]string, stripPathComp
 	if strings.HasSuffix(url, ".gz") {
 		gzr, err := gzip.NewReader(&buf)
 		if err != nil {
-			return errors.Errorf("unable to gunzip response")
+			return errors.New("unable to gunzip response")
 		}
 
 		r = gzr
@@ -280,6 +280,6 @@ func downloadInternal(url, dir string, checksum map[string]string, stripPathComp
 	case strings.HasSuffix(url, ".zip"):
 		return errors.Wrap(unzip(dir, r, stripPathComponents), "unzip error")
 	default:
-		return errors.Errorf("unsupported archive format")
+		return errors.New("unsupported archive format")
 	}
 }


Test patch:
diff --git a/internal/blobcrypto/blob_crypto_test.go b/internal/blobcrypto/blob_crypto_test.go
index 83d13ad3..dd22e6c1 100644
--- a/internal/blobcrypto/blob_crypto_test.go
+++ b/internal/blobcrypto/blob_crypto_test.go
@@ -60,11 +60,11 @@ func TestBlobCrypto(t *testing.T) {
 type badEncryptor struct{}
 
 func (badEncryptor) Encrypt(input gather.Bytes, contentID []byte, output *gather.WriteBuffer) error {
-	return errors.Errorf("some error")
+	return errors.New("some error")
 }
 
 func (badEncryptor) Decrypt(input gather.Bytes, contentID []byte, output *gather.WriteBuffer) error {
-	return errors.Errorf("some error")
+	return errors.New("some error")
 }
 
 func (badEncryptor) Overhead() int { return 0 }
diff --git a/internal/cache/cache_storage_test.go b/internal/cache/cache_storage_test.go
index e08c56fd..1e55f82c 100644
--- a/internal/cache/cache_storage_test.go
+++ b/internal/cache/cache_storage_test.go
@@ -28,7 +28,7 @@ func TestNewStorageOrNil(t *testing.T) {
 	_, err = NewStorageOrNil(ctx, "relative/path/to/cache/dir", 1000, "subdir")
 	require.Error(t, err)
 
-	someError := errors.Errorf("some error")
+	someError := errors.New("some error")
 
 	oldMkdirAll := mkdirAll
 
diff --git a/internal/cache/content_cache_test.go b/internal/cache/content_cache_test.go
index db859ca0..9069c225 100644
--- a/internal/cache/content_cache_test.go
+++ b/internal/cache/content_cache_test.go
@@ -195,8 +195,8 @@ func verifyContentCache(t *testing.T, cc cache.ContentCache, cacheStorage blob.S
 			{"xf0f0f3", "no-such-content", 0, -1, nil, blob.ErrBlobNotFound},
 			{"xf0f0f4", "no-such-content", 10, 5, nil, blob.ErrBlobNotFound},
 			{"f0f0f5", "content-1", 7, 3, []byte{8, 9, 10}, nil},
-			{"xf0f0f6", "content-1", 11, 10, nil, errors.Errorf("invalid offset: 11: invalid blob offset or length")},
-			{"xf0f0f6", "content-1", -1, 5, nil, errors.Errorf("invalid offset: -1: invalid blob offset or length")},
+			{"xf0f0f6", "content-1", 11, 10, nil, errors.New("invalid offset: 11: invalid blob offset or length")},
+			{"xf0f0f6", "content-1", -1, 5, nil, errors.New("invalid offset: -1: invalid blob offset or length")},
 		}
 
 		var v gather.WriteBuffer
@@ -356,5 +356,5 @@ type withoutTouchBlob struct {
 }
 
 func (c withoutTouchBlob) TouchBlob(ctx context.Context, blobID blob.ID, threshold time.Duration) (time.Time, error) {
-	return time.Time{}, errors.Errorf("TouchBlob not implemented")
+	return time.Time{}, errors.New("TouchBlob not implemented")
 }
diff --git a/internal/cache/persistent_lru_cache_test.go b/internal/cache/persistent_lru_cache_test.go
index c50a8372..32db59dc 100644
--- a/internal/cache/persistent_lru_cache_test.go
+++ b/internal/cache/persistent_lru_cache_test.go
@@ -87,7 +87,7 @@ func TestPersistentLRUCache(t *testing.T) {
 	}, nil, clock.Now)
 	require.NoError(t, err)
 
-	someError := errors.Errorf("some error")
+	someError := errors.New("some error")
 
 	var tmp2 gather.WriteBuffer
 	defer tmp2.Close()
@@ -126,7 +126,7 @@ func TestPersistentLRUCache_Invalid(t *testing.T) {
 
 	ctx := testlogging.ContextWithLevel(t, testlogging.LevelInfo)
 
-	someError := errors.Errorf("some error")
+	someError := errors.New("some error")
 
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 	fs := blobtesting.NewFaultyStorage(st)
@@ -144,7 +144,7 @@ func TestPersistentLRUCache_GetDeletesInvalidBlob(t *testing.T) {
 
 	ctx := testlogging.ContextWithLevel(t, testlogging.LevelInfo)
 
-	someError := errors.Errorf("some error")
+	someError := errors.New("some error")
 
 	data := blobtesting.DataMap{}
 
@@ -176,7 +176,7 @@ func TestPersistentLRUCache_PutIgnoresStorageFailure(t *testing.T) {
 
 	ctx := testlogging.ContextWithLevel(t, testlogging.LevelInfo)
 
-	someError := errors.Errorf("some error")
+	someError := errors.New("some error")
 
 	data := blobtesting.DataMap{}
 
@@ -222,7 +222,7 @@ func TestPersistentLRUCache_SweepMinSweepAge(t *testing.T) {
 	time.Sleep(1 * time.Second)
 
 	// simulate error during final sweep
-	fs.AddFault(blobtesting.MethodListBlobs).ErrorInstead(errors.Errorf("some error"))
+	fs.AddFault(blobtesting.MethodListBlobs).ErrorInstead(errors.New("some error"))
 	pc.Close(ctx)
 
 	// both keys are retained since we're under min sweep age
@@ -248,14 +248,14 @@ func TestPersistentLRUCache_SweepIgnoresErrors(t *testing.T) {
 	require.NoError(t, err)
 
 	// ignore delete errors forever
-	fs.AddFault(blobtesting.MethodDeleteBlob).ErrorInstead(errors.Errorf("some delete error")).Repeat(1e6)
+	fs.AddFault(blobtesting.MethodDeleteBlob).ErrorInstead(errors.New("some delete error")).Repeat(1e6)
 
 	pc.Put(ctx, "key", gather.FromSlice([]byte{1, 2, 3}))
 	pc.Put(ctx, "key2", gather.FromSlice(bytes.Repeat([]byte{1, 2, 3}, 10)))
 	time.Sleep(500 * time.Millisecond)
 
 	// simulate error during sweep
-	fs.AddFaults(blobtesting.MethodListBlobs, fault.New().ErrorInstead(errors.Errorf("some error")))
+	fs.AddFaults(blobtesting.MethodListBlobs, fault.New().ErrorInstead(errors.New("some error")))
 
 	time.Sleep(500 * time.Millisecond)
 
@@ -286,7 +286,7 @@ func TestPersistentLRUCache_Sweep1(t *testing.T) {
 	time.Sleep(1 * time.Second)
 
 	// simulate error during final sweep
-	fs.AddFaults(blobtesting.MethodListBlobs, fault.New().ErrorInstead(errors.Errorf("some error")))
+	fs.AddFaults(blobtesting.MethodListBlobs, fault.New().ErrorInstead(errors.New("some error")))
 	pc.Close(ctx)
 }
 
@@ -305,7 +305,7 @@ func TestPersistentLRUCacheNil(t *testing.T) {
 
 	called := false
 
-	dummyError := errors.Errorf("dummy error")
+	dummyError := errors.New("dummy error")
 
 	require.ErrorIs(t, pc.GetOrLoad(ctx, "key", func(output *gather.WriteBuffer) error {
 		called = true
diff --git a/internal/dirutil/mssubdirall_test.go b/internal/dirutil/mssubdirall_test.go
index 3413eeda..8b693768 100644
--- a/internal/dirutil/mssubdirall_test.go
+++ b/internal/dirutil/mssubdirall_test.go
@@ -59,7 +59,7 @@ func TestMkSubdirAll(t *testing.T) {
 		}
 	}
 
-	osi.mkdirErr = errors.Errorf("some error")
+	osi.mkdirErr = errors.New("some error")
 
 	require.ErrorIs(t, dirutil.MkSubdirAll(osi, td, filepath.Join(td, "somedir4"), 0o755), osi.mkdirErr)
 }
diff --git a/internal/epoch/epoch_manager_test.go b/internal/epoch/epoch_manager_test.go
index 178d326c..abc4ed76 100644
--- a/internal/epoch/epoch_manager_test.go
+++ b/internal/epoch/epoch_manager_test.go
@@ -80,7 +80,7 @@ func (te *epochManagerTestEnv) interruptedCompaction(ctx context.Context, _ []bl
 	te.st.PutBlob(ctx, blob.ID(fmt.Sprintf("%v%016x-s%v-c3", prefix, sess, rand.Int63())), gather.FromSlice([]byte("dummy")), blob.PutOptions{})
 	te.st.PutBlob(ctx, blob.ID(fmt.Sprintf("%v%016x-s%v-c3", prefix, sess, rand.Int63())), gather.FromSlice([]byte("dummy")), blob.PutOptions{})
 
-	return errors.Errorf("failed for some reason")
+	return errors.New("failed for some reason")
 }
 
 func newTestEnv(t *testing.T) *epochManagerTestEnv {
@@ -319,7 +319,7 @@ func TestIndexEpochManager_DeletionFailing(t *testing.T) {
 
 	te.faultyStorage.
 		AddFault(blobtesting.MethodDeleteBlob).
-		ErrorInstead(errors.Errorf("something bad happened")).
+		ErrorInstead(errors.New("something bad happened")).
 		Repeat(200)
 
 	// set up test environment in which compactions never succeed for whatever reason.
@@ -772,7 +772,7 @@ func TestInvalid_WriteIndex(t *testing.T) {
 	defer cancel()
 
 	// on first write, advance time enough to lose current context and go to the next epoch.
-	te.faultyStorage.AddFault(blobtesting.MethodListBlobs).Repeat(100).Before(cancel).ErrorInstead(errors.Errorf("canceled"))
+	te.faultyStorage.AddFault(blobtesting.MethodListBlobs).Repeat(100).Before(cancel).ErrorInstead(errors.New("canceled"))
 
 	_, err := te.writeIndexFiles(ctx,
 		newFakeIndexWithEntries(1),
@@ -793,7 +793,7 @@ func TestInvalid_ForceAdvanceEpoch(t *testing.T) {
 	require.ErrorIs(t, err, ctx.Err())
 
 	ctx = testlogging.Context(t)
-	someError := errors.Errorf("failed")
+	someError := errors.New("failed")
 	te.faultyStorage.AddFault(blobtesting.MethodPutBlob).ErrorInstead(someError)
 
 	err = te.mgr.forceAdvanceEpoch(ctx)
diff --git a/internal/gather/gather_bytes_test.go b/internal/gather/gather_bytes_test.go
index 6e1d195e..b8438749 100644
--- a/internal/gather/gather_bytes_test.go
+++ b/internal/gather/gather_bytes_test.go
@@ -122,7 +122,7 @@ func() {
 
 			require.Equal(t, tmp.ToByteSlice(), b.ToByteSlice())
 
-			someError := errors.Errorf("some error")
+			someError := errors.New("some error")
 
 			// WriteTo propagates error
 			if b.Length() > 0 {
diff --git a/internal/impossible/impossible_test.go b/internal/impossible/impossible_test.go
index 99ae0a12..f6d464d3 100644
--- a/internal/impossible/impossible_test.go
+++ b/internal/impossible/impossible_test.go
@@ -12,7 +12,7 @@
 func TestImpossible(t *testing.T) {
 	impossible.PanicOnError(nil)
 
-	someErr := errors.Errorf("some error")
+	someErr := errors.New("some error")
 	require.PanicsWithError(t, someErr.Error(), func() {
 		impossible.PanicOnError(someErr)
 	})
diff --git a/internal/repodiag/blob_writer_test.go b/internal/repodiag/blob_writer_test.go
index aeeb5bc0..d580f6ee 100644
--- a/internal/repodiag/blob_writer_test.go
+++ b/internal/repodiag/blob_writer_test.go
@@ -41,7 +41,7 @@ func TestDiagWriter(t *testing.T) {
 	<-closeCalled2
 
 	// simulate write failure
-	someErr := errors.Errorf("some error")
+	someErr := errors.New("some error")
 	fs.AddFault(blobtesting.MethodPutBlob).ErrorInstead(someErr)
 
 	closeCalled3 := make(chan struct{})
diff --git a/internal/repotesting/reconnectable_storage.go b/internal/repotesting/reconnectable_storage.go
index 1229d15e..aee2e56d 100644
--- a/internal/repotesting/reconnectable_storage.go
+++ b/internal/repotesting/reconnectable_storage.go
@@ -59,7 +59,7 @@ func (s reconnectableStorage) ConnectionInfo() blob.ConnectionInfo {
 // New creates new reconnectable storage.
 func New(ctx context.Context, opt *ReconnectableStorageOptions, isCreate bool) (blob.Storage, error) {
 	if opt.UUID == "" {
-		return nil, errors.Errorf("missing UUID")
+		return nil, errors.New("missing UUID")
 	}
 
 	v, ok := reconnectableStorageByUUID.Load(opt.UUID)
diff --git a/internal/retry/retry_test.go b/internal/retry/retry_test.go
index 6f2f2c39..a51d4d69 100644
--- a/internal/retry/retry_test.go
+++ b/internal/retry/retry_test.go
@@ -39,7 +39,7 @@ func TestRetry(t *testing.T) {
 			}
 			return 4, nil
 		}, 4, nil},
-		{"retriable-never-succeeds", func() (int, error) { return 0, errRetriable }, 0, errors.Errorf("unable to complete retriable-never-succeeds despite 3 retries")},
+		{"retriable-never-succeeds", func() (int, error) { return 0, errRetriable }, 0, errors.New("unable to complete retriable-never-succeeds despite 3 retries")},
 	}
 
 	ctx := testlogging.Context(t)
diff --git a/internal/server/server_maintenance_test.go b/internal/server/server_maintenance_test.go
index 9a3396d3..cade0639 100644
--- a/internal/server/server_maintenance_test.go
+++ b/internal/server/server_maintenance_test.go
@@ -78,7 +78,7 @@ func TestServerMaintenance(t *testing.T) {
 	}, 3*time.Second, 10*time.Millisecond)
 
 	ts.mu.Lock()
-	ts.err = errors.Errorf("some error")
+	ts.err = errors.New("some error")
 	ts.mu.Unlock()
 
 	mm.trigger()
diff --git a/internal/server/server_test.go b/internal/server/server_test.go
index b15ec9bc..9d3f33ac 100644
--- a/internal/server/server_test.go
+++ b/internal/server/server_test.go
@@ -190,7 +190,7 @@ func remoteRepositoryTest(ctx context.Context, t *testing.T, rep repo.Repository
 		require.NoError(t, w.Flush(ctx))
 
 		if uploaded == 0 {
-			return errors.Errorf("did not report uploaded bytes")
+			return errors.New("did not report uploaded bytes")
 		}
 
 		uploaded = 0
@@ -198,7 +198,7 @@ func remoteRepositoryTest(ctx context.Context, t *testing.T, rep repo.Repository
 		require.NoError(t, w.Flush(ctx))
 
 		if uploaded != 0 {
-			return errors.Errorf("unexpected upload when writing duplicate object")
+			return errors.New("unexpected upload when writing duplicate object")
 		}
 
 		if result != result2 {
@@ -218,7 +218,7 @@ func remoteRepositoryTest(ctx context.Context, t *testing.T, rep repo.Repository
 
 		_, err = ow.Result()
 		if err == nil {
-			return errors.Errorf("unexpected success writing object with 'm' prefix")
+			return errors.New("unexpected success writing object with 'm' prefix")
 		}
 
 		manifestID, err = snapshot.SaveSnapshot(ctx, w, &snapshot.Manifest{
diff --git a/internal/uitask/uitask_test.go b/internal/uitask/uitask_test.go
index 29f51484..c6edbdef 100644
--- a/internal/uitask/uitask_test.go
+++ b/internal/uitask/uitask_test.go
@@ -185,7 +185,7 @@ func testUITaskInternal(t *testing.T, ctx context.Context, m *uitask.Manager) {
 			t.Fatalf("unexpected summary: %v", diff)
 		}
 
-		return errors.Errorf("some error")
+		return errors.New("some error")
 	})
 
 	verifyTaskList(t, m, map[string]uitask.Status{
diff --git a/repo/blob/filesystem/osinterface_mock_other_test.go b/repo/blob/filesystem/osinterface_mock_other_test.go
index e521fbc4..7d6f8991 100644
--- a/repo/blob/filesystem/osinterface_mock_other_test.go
+++ b/repo/blob/filesystem/osinterface_mock_other_test.go
@@ -12,7 +12,7 @@
 
 func (osi *mockOS) Stat(fname string) (fs.FileInfo, error) {
 	if osi.statRemainingErrors.Add(-1) >= 0 {
-		return nil, &os.PathError{Op: "stat", Err: errors.Errorf("underlying problem")}
+		return nil, &os.PathError{Op: "stat", Err: errors.New("underlying problem")}
 	}
 
 	return osi.osInterface.Stat(fname)
diff --git a/repo/blob/filesystem/osinterface_mock_test.go b/repo/blob/filesystem/osinterface_mock_test.go
index e2a816d1..fc1a9d22 100644
--- a/repo/blob/filesystem/osinterface_mock_test.go
+++ b/repo/blob/filesystem/osinterface_mock_test.go
@@ -10,7 +10,7 @@
 	"github.com/pkg/errors"
 )
 
-var errNonRetriable = errors.Errorf("some non-retriable error")
+var errNonRetriable = errors.New("some non-retriable error")
 
 type mockOS struct {
 	readFileRemainingErrors             atomic.Int32
@@ -53,7 +53,7 @@ func (osi *mockOS) Open(fname string) (osReadFile, error) {
 
 func (osi *mockOS) Rename(oldname, newname string) error {
 	if osi.renameRemainingErrors.Add(-1) >= 0 {
-		return &os.LinkError{Op: "rename", Old: oldname, New: newname, Err: errors.Errorf("underlying problem")}
+		return &os.LinkError{Op: "rename", Old: oldname, New: newname, Err: errors.New("underlying problem")}
 	}
 
 	return osi.osInterface.Rename(oldname, newname)
@@ -63,7 +63,7 @@ func (osi *mockOS) IsPathSeparator(c byte) bool { return os.IsPathSeparator(c) }
 
 func (osi *mockOS) ReadDir(dirname string) ([]fs.DirEntry, error) {
 	if osi.readDirRemainingErrors.Add(-1) >= 0 {
-		return nil, &os.PathError{Op: "readdir", Err: errors.Errorf("underlying problem")}
+		return nil, &os.PathError{Op: "readdir", Err: errors.New("underlying problem")}
 	}
 
 	if osi.readDirRemainingNonRetriableErrors.Add(-1) >= 0 {
@@ -88,7 +88,7 @@ func (osi *mockOS) ReadDir(dirname string) ([]fs.DirEntry, error) {
 
 func (osi *mockOS) Remove(fname string) error {
 	if osi.removeRemainingRetriableErrors.Add(-1) >= 0 {
-		return &os.PathError{Op: "unlink", Err: errors.Errorf("underlying problem")}
+		return &os.PathError{Op: "unlink", Err: errors.New("underlying problem")}
 	}
 
 	if osi.removeRemainingNonRetriableErrors.Add(-1) >= 0 {
@@ -100,7 +100,7 @@ func (osi *mockOS) Remove(fname string) error {
 
 func (osi *mockOS) Chtimes(fname string, atime, mtime time.Time) error {
 	if osi.chtimesRemainingErrors.Add(-1) >= 0 {
-		return &os.PathError{Op: "chtimes", Err: errors.Errorf("underlying problem")}
+		return &os.PathError{Op: "chtimes", Err: errors.New("underlying problem")}
 	}
 
 	return osi.osInterface.Chtimes(fname, atime, mtime)
@@ -108,7 +108,7 @@ func (osi *mockOS) Chtimes(fname string, atime, mtime time.Time) error {
 
 func (osi *mockOS) Chown(fname string, uid, gid int) error {
 	if osi.chownRemainingErrors.Add(-1) >= 0 {
-		return &os.PathError{Op: "chown", Err: errors.Errorf("underlying problem")}
+		return &os.PathError{Op: "chown", Err: errors.New("underlying problem")}
 	}
 
 	return osi.osInterface.Chown(fname, uid, gid)
@@ -116,7 +116,7 @@ func (osi *mockOS) Chown(fname string, uid, gid int) error {
 
 func (osi *mockOS) CreateNewFile(fname string, perm os.FileMode) (osWriteFile, error) {
 	if osi.createNewFileRemainingErrors.Add(-1) >= 0 {
-		return nil, &os.PathError{Op: "create", Err: errors.Errorf("underlying problem")}
+		return nil, &os.PathError{Op: "create", Err: errors.New("underlying problem")}
 	}
 
 	wf, err := osi.osInterface.CreateNewFile(fname, perm)
@@ -137,7 +137,7 @@ func (osi *mockOS) CreateNewFile(fname string, perm os.FileMode) (osWriteFile, e
 
 func (osi *mockOS) Mkdir(fname string, mode os.FileMode) error {
 	if osi.mkdirAllRemainingErrors.Add(-1) >= 0 {
-		return &os.PathError{Op: "mkdir", Err: errors.Errorf("underlying problem")}
+		return &os.PathError{Op: "mkdir", Err: errors.New("underlying problem")}
 	}
 
 	return osi.osInterface.Mkdir(fname, mode)
@@ -152,7 +152,7 @@ type readFailureFile struct {
 }
 
 func (f readFailureFile) Read(b []byte) (int, error) {
-	return 0, &os.PathError{Op: "read", Err: errors.Errorf("underlying problem")}
+	return 0, &os.PathError{Op: "read", Err: errors.New("underlying problem")}
 }
 
 type writeFailureFile struct {
@@ -160,7 +160,7 @@ type writeFailureFile struct {
 }
 
 func (f writeFailureFile) Write(b []byte) (int, error) {
-	return 0, &os.PathError{Op: "write", Err: errors.Errorf("underlying problem")}
+	return 0, &os.PathError{Op: "write", Err: errors.New("underlying problem")}
 }
 
 type writeCloseFailureFile struct {
@@ -168,7 +168,7 @@ type writeCloseFailureFile struct {
 }
 
 func (f writeCloseFailureFile) Close() error {
-	return &os.PathError{Op: "close", Err: errors.Errorf("underlying problem")}
+	return &os.PathError{Op: "close", Err: errors.New("underlying problem")}
 }
 
 type mockDirEntryInfoError struct {
diff --git a/repo/blob/filesystem/osinterface_mock_unix_test.go b/repo/blob/filesystem/osinterface_mock_unix_test.go
index 424408e1..271d30cb 100644
--- a/repo/blob/filesystem/osinterface_mock_unix_test.go
+++ b/repo/blob/filesystem/osinterface_mock_unix_test.go
@@ -13,7 +13,7 @@
 
 func (osi *mockOS) Stat(fname string) (fs.FileInfo, error) {
 	if osi.statRemainingErrors.Add(-1) >= 0 {
-		return nil, &os.PathError{Op: "stat", Err: errors.Errorf("underlying problem")}
+		return nil, &os.PathError{Op: "stat", Err: errors.New("underlying problem")}
 	}
 
 	if osi.eStaleRemainingErrors.Add(-1) >= 0 {
diff --git a/repo/blob/storage_test.go b/repo/blob/storage_test.go
index d9b87be6..60e9ddcd 100644
--- a/repo/blob/storage_test.go
+++ b/repo/blob/storage_test.go
@@ -90,7 +90,7 @@ func TestIterateAllPrefixesInParallel(t *testing.T) {
 
 	require.ElementsMatch(t, []blob.ID{"foo", "bar", "boo"}, got)
 
-	errDummy := errors.Errorf("dummy")
+	errDummy := errors.New("dummy")
 
 	require.ErrorIs(t, errDummy, blob.IterateAllPrefixesInParallel(ctx, 10, st, []blob.ID{
 		"b",
diff --git a/repo/blob/storagemetrics/storage_metrics_test.go b/repo/blob/storagemetrics/storage_metrics_test.go
index 91c46788..05141b93 100644
--- a/repo/blob/storagemetrics/storage_metrics_test.go
+++ b/repo/blob/storagemetrics/storage_metrics_test.go
@@ -16,7 +16,7 @@
 
 func TestStorageMetrics_PutBlob(t *testing.T) {
 	ctx := testlogging.Context(t)
-	someError := errors.Errorf("foo")
+	someError := errors.New("foo")
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 
 	fs := blobtesting.NewFaultyStorage(st)
@@ -42,7 +42,7 @@ func TestStorageMetrics_PutBlob(t *testing.T) {
 
 func TestStorageMetrics_GetBlob(t *testing.T) {
 	ctx := testlogging.Context(t)
-	someError := errors.Errorf("foo")
+	someError := errors.New("foo")
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 
 	require.NoError(t, st.PutBlob(ctx, "someBlob", gather.FromSlice([]byte{1, 2, 3, 4, 5}), blob.PutOptions{}))
@@ -84,7 +84,7 @@ func TestStorageMetrics_GetBlob(t *testing.T) {
 
 func TestStorageMetrics_GetMetadata(t *testing.T) {
 	ctx := testlogging.Context(t)
-	someError := errors.Errorf("foo")
+	someError := errors.New("foo")
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 
 	require.NoError(t, st.PutBlob(ctx, "someBlob", gather.FromSlice([]byte{1, 2, 3, 4, 5}), blob.PutOptions{}))
@@ -116,7 +116,7 @@ func TestStorageMetrics_GetMetadata(t *testing.T) {
 
 func TestStorageMetrics_GetCapacity(t *testing.T) {
 	ctx := testlogging.Context(t)
-	someError := errors.Errorf("foo")
+	someError := errors.New("foo")
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 
 	fs := blobtesting.NewFaultyStorage(st)
@@ -146,7 +146,7 @@ func TestStorageMetrics_GetCapacity(t *testing.T) {
 
 func TestStorageMetrics_DeleteBlob(t *testing.T) {
 	ctx := testlogging.Context(t)
-	someError := errors.Errorf("foo")
+	someError := errors.New("foo")
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 
 	require.NoError(t, st.PutBlob(ctx, "someBlob", gather.FromSlice([]byte{1, 2, 3, 4, 5}), blob.PutOptions{}))
@@ -178,7 +178,7 @@ func TestStorageMetrics_DeleteBlob(t *testing.T) {
 
 func TestStorageMetrics_Close(t *testing.T) {
 	ctx := testlogging.Context(t)
-	someError := errors.Errorf("foo")
+	someError := errors.New("foo")
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 
 	fs := blobtesting.NewFaultyStorage(st)
@@ -208,7 +208,7 @@ func TestStorageMetrics_Close(t *testing.T) {
 
 func TestStorageMetrics_FlushCaches(t *testing.T) {
 	ctx := testlogging.Context(t)
-	someError := errors.Errorf("foo")
+	someError := errors.New("foo")
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 
 	fs := blobtesting.NewFaultyStorage(st)
@@ -238,7 +238,7 @@ func TestStorageMetrics_FlushCaches(t *testing.T) {
 
 func TestStorageMetrics_ListBlobs(t *testing.T) {
 	ctx := testlogging.Context(t)
-	someError := errors.Errorf("foo")
+	someError := errors.New("foo")
 	st := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, nil)
 	require.NoError(t, st.PutBlob(ctx, "someBlob1", gather.FromSlice([]byte{1, 2, 3, 4, 5}), blob.PutOptions{}))
 	require.NoError(t, st.PutBlob(ctx, "someBlob2", gather.FromSlice([]byte{1, 2, 3, 4, 5}), blob.PutOptions{}))
diff --git a/repo/content/content_manager_test.go b/repo/content/content_manager_test.go
index 4d8bc9cf..06587480 100644
--- a/repo/content/content_manager_test.go
+++ b/repo/content/content_manager_test.go
@@ -1250,7 +1250,7 @@ func (s *contentManagerSuite) TestHandleWriteErrors(t *testing.T) {
 				}
 			} else {
 				if cnt > 0 {
-					result = append(result, fault.New().Repeat(cnt-1).ErrorInstead(errors.Errorf("some write error")))
+					result = append(result, fault.New().Repeat(cnt-1).ErrorInstead(errors.New("some write error")))
 				}
 			}
 		}
diff --git a/repo/content/index/merged_test.go b/repo/content/index/merged_test.go
index cffd641d..e22d419c 100644
--- a/repo/content/index/merged_test.go
+++ b/repo/content/index/merged_test.go
@@ -60,7 +60,7 @@ func TestMerged(t *testing.T) {
 	fmt.Println("=========== START")
 
 	// error is propagated.
-	someErr := errors.Errorf("some error")
+	someErr := errors.New("some error")
 	require.ErrorIs(t, m.Iterate(AllIDs, func(i Info) error {
 		if i.ContentID == mustParseID(t, "aabbcc") {
 			return someErr
@@ -160,7 +160,7 @@ func (i failingIndex) GetInfo(contentID ID, result *Info) (bool, error) {
 }
 
 func TestMergedGetInfoError(t *testing.T) {
-	someError := errors.Errorf("some error")
+	someError := errors.New("some error")
 
 	m := Merged{failingIndex{nil, someError}}
 
diff --git a/repo/content/indexblob/index_blob_encryption_test.go b/repo/content/indexblob/index_blob_encryption_test.go
index b57f673a..88bbf6ba 100644
--- a/repo/content/indexblob/index_blob_encryption_test.go
+++ b/repo/content/indexblob/index_blob_encryption_test.go
@@ -68,14 +68,14 @@ func TestEncryptedBlobManager(t *testing.T) {
 
 	require.ErrorIs(t, ebm.GetEncryptedBlob(ctx, "no-such-blob", &tmp), blob.ErrBlobNotFound)
 
-	someError := errors.Errorf("some error")
+	someError := errors.New("some error")
 
 	fs.AddFault(blobtesting.MethodPutBlob).ErrorInstead(someError)
 
 	_, err = ebm.EncryptAndWriteBlob(ctx, gather.FromSlice([]byte{1, 2, 3, 4}), "x", "session1")
 	require.ErrorIs(t, err, someError)
 
-	someError2 := errors.Errorf("some error 2")
+	someError2 := errors.New("some error 2")
 
 	ebm.crypter = blobcrypto.StaticCrypter{Hash: hf, Encryption: failingEncryptor{nil, someError2}}
 
diff --git a/repo/format/format_manager_test.go b/repo/format/format_manager_test.go
index 2a3e3db3..d286b64b 100644
--- a/repo/format/format_manager_test.go
+++ b/repo/format/format_manager_test.go
@@ -22,7 +22,7 @@
 )
 
 var (
-	errSomeError = errors.Errorf("some error")
+	errSomeError = errors.New("some error")
 
 	cf = format.ContentFormat{
 		MutableParameters: format.MutableParameters{
diff --git a/repo/object/object_manager_test.go b/repo/object/object_manager_test.go
index 797c4495..2fd359b8 100644
--- a/repo/object/object_manager_test.go
+++ b/repo/object/object_manager_test.go
@@ -29,7 +29,7 @@
 	"github.com/kopia/kopia/repo/splitter"
 )
 
-var errSomeError = errors.Errorf("some error")
+var errSomeError = errors.New("some error")
 
 type fakeContentManager struct {
 	mu sync.Mutex
@@ -369,7 +369,7 @@ func TestObjectWriterRaceBetweenCheckpointAndResult(t *testing.T) {
 
 				for _, id := range ids {
 					if id == content.EmptyID {
-						return errors.Errorf("checkpoint returned empty id")
+						return errors.New("checkpoint returned empty id")
 					}
 				}
 			}
diff --git a/repo/repository_test.go b/repo/repository_test.go
index cf8b17ce..68832af4 100644
--- a/repo/repository_test.go
+++ b/repo/repository_test.go
@@ -619,7 +619,7 @@ func TestWriteSessionFlushOnSuccess(t *testing.T) {
 
 	verify(ctx, t, env.Repository, oid, []byte{1, 2, 3}, "test-1")
 
-	someErr := errors.Errorf("some error")
+	someErr := errors.New("some error")
 
 	require.ErrorIs(t, repo.WriteSession(ctx, env.Repository, repo.WriteSessionOptions{}, func(ctx context.Context, w repo.RepositoryWriter) error {
 		oid = writeObject(ctx, t, w, []byte{1, 2, 3, 4}, "test-2")
@@ -684,7 +684,7 @@ func(ctx context.Context, w repo.RepositoryWriter) error {
 
 	verify(ctx, t, rep, oid, []byte{1, 2, 3}, "test-1")
 
-	someErr := errors.Errorf("some error")
+	someErr := errors.New("some error")
 
 	require.ErrorIs(t, repo.WriteSession(ctx, rep, repo.WriteSessionOptions{}, func(ctx context.Context, w repo.RepositoryWriter) error {
 		oid = writeObject(ctx, t, w, []byte{1, 2, 3, 4}, "test-2")
diff --git a/snapshot/snapshotfs/snapshot_tree_walker_test.go b/snapshot/snapshotfs/snapshot_tree_walker_test.go
index 59ebcb0c..e6951eb8 100644
--- a/snapshot/snapshotfs/snapshot_tree_walker_test.go
+++ b/snapshot/snapshotfs/snapshot_tree_walker_test.go
@@ -80,7 +80,7 @@ func TestSnapshotTreeWalker(t *testing.T) {
 }
 
 func TestSnapshotTreeWalker_Errors(t *testing.T) {
-	someErr1 := errors.Errorf("some error")
+	someErr1 := errors.New("some error")
 
 	ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
 
@@ -122,7 +122,7 @@ func TestSnapshotTreeWalker_Errors(t *testing.T) {
 }
 
 func TestSnapshotTreeWalker_MultipleErrors(t *testing.T) {
-	someErr1 := errors.Errorf("some error")
+	someErr1 := errors.New("some error")
 
 	ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
 
@@ -172,7 +172,7 @@ func TestSnapshotTreeWalker_MultipleErrors(t *testing.T) {
 }
 
 func TestSnapshotTreeWalker_MultipleErrorsSameOID(t *testing.T) {
-	someErr1 := errors.Errorf("some error")
+	someErr1 := errors.New("some error")
 
 	ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
 
diff --git a/snapshot/snapshotfs/snapshot_verifier_test.go b/snapshot/snapshotfs/snapshot_verifier_test.go
index 49f58b4a..4b60cf5f 100644
--- a/snapshot/snapshotfs/snapshot_verifier_test.go
+++ b/snapshot/snapshotfs/snapshot_verifier_test.go
@@ -56,7 +56,7 @@ func TestSnapshotVerifier(t *testing.T) {
 
 		v := snapshotfs.NewVerifier(ctx, te2, opts)
 
-		someErr := errors.Errorf("some error")
+		someErr := errors.New("some error")
 
 		require.ErrorIs(t, v.InParallel(ctx, func(tw *snapshotfs.TreeWalker) error {
 			return someErr
diff --git a/snapshot/snapshotfs/upload_test.go b/snapshot/snapshotfs/upload_test.go
index 279ed8f2..f249574a 100644
--- a/snapshot/snapshotfs/upload_test.go
+++ b/snapshot/snapshotfs/upload_test.go
@@ -357,8 +357,8 @@ func TestUpload_ErrorEntries(t *testing.T) {
 	defer th.cleanup()
 
 	th.sourceDir.Subdir("d1").AddErrorEntry("some-unknown-entry", os.ModeIrregular, fs.ErrUnknown)
-	th.sourceDir.Subdir("d1").AddErrorEntry("some-failed-entry", 0, errors.Errorf("some-other-error"))
-	th.sourceDir.Subdir("d2").AddErrorEntry("another-failed-entry", os.ModeIrregular, errors.Errorf("another-error"))
+	th.sourceDir.Subdir("d1").AddErrorEntry("some-failed-entry", 0, errors.New("some-other-error"))
+	th.sourceDir.Subdir("d2").AddErrorEntry("another-failed-entry", os.ModeIrregular, errors.New("another-error"))
 
 	trueValue := policy.OptionalBool(true)
 	falseValue := policy.OptionalBool(false)
diff --git a/tests/htmlui_e2e_test/context_test.go b/tests/htmlui_e2e_test/context_test.go
index 99e6b978..884d95d7 100644
--- a/tests/htmlui_e2e_test/context_test.go
+++ b/tests/htmlui_e2e_test/context_test.go
@@ -46,7 +46,7 @@ func (tc *TestContext) waitForDownload(waitTime time.Duration) chromedp.Action {
 			tc.t.Logf("file downloaded, good!")
 
 		case <-time.After(waitTime):
-			return errors.Errorf("download did not complete")
+			return errors.New("download did not complete")
 		}
 
 		return nil
diff --git a/tests/perf_benchmark/process_results.go b/tests/perf_benchmark/process_results.go
index 59d935d4..8a558a8f 100644
--- a/tests/perf_benchmark/process_results.go
+++ b/tests/perf_benchmark/process_results.go
@@ -108,7 +108,7 @@ func parseRepoSize(fname string) (int64, error) {
 
 	fields := strings.Fields(s.Text())
 	if len(fields) != 2 {
-		return 0, errors.Errorf("invalid repo size format")
+		return 0, errors.New("invalid repo size format")
 	}
 
 	return strconv.ParseInt(fields[0], 10, 64)
diff --git a/tests/repository_stress_test/repository_stress_test.go b/tests/repository_stress_test/repository_stress_test.go
index 66e5773e..52171ff4 100644
--- a/tests/repository_stress_test/repository_stress_test.go
+++ b/tests/repository_stress_test/repository_stress_test.go
@@ -74,7 +74,7 @@ type StressOptions struct {
 	ActionWeights map[actName]int
 }
 
-var errSkipped = errors.Errorf("skipped")
+var errSkipped = errors.New("skipped")
 
 const masterPassword = "foo-bar-baz-1234"