diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index bddfcf8e36..0423d16e30 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -17,7 +17,7 @@ jobs:
         with:
           go-version-file: go.mod
       - name: golangci-lint
-        uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0
+        uses: golangci/golangci-lint-action@4696ba8babb6127d732c3c6dde519db15edab9ea # v6.5.1
         with:
-          version: v1.55.1
+          version: v1.61.0
           args: --timeout=8m
diff --git a/.github/workflows/test_crdb.yaml b/.github/workflows/test_crdb.yaml
index 4ccece1152..755ad4dcf2 100644
--- a/.github/workflows/test_crdb.yaml
+++ b/.github/workflows/test_crdb.yaml
@@ -25,9 +25,9 @@ jobs:
         check-latest: true
         cache: true
 
-    - uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0
+    - uses: golangci/golangci-lint-action@4696ba8babb6127d732c3c6dde519db15edab9ea # v6.5.1
       with:
-        version: 'v1.55.1'
+        version: 'v1.61.0'
         args: ./storage/crdb
 
   unit-test:
diff --git a/.github/workflows/test_pgdb.yaml b/.github/workflows/test_pgdb.yaml
index 5baf50e11b..1d8133f452 100644
--- a/.github/workflows/test_pgdb.yaml
+++ b/.github/workflows/test_pgdb.yaml
@@ -25,9 +25,9 @@ jobs:
         check-latest: true
         cache: true
 
-    - uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0
+    - uses: golangci/golangci-lint-action@4696ba8babb6127d732c3c6dde519db15edab9ea # v6.5.1
       with:
-        version: 'v1.55.1'
+        version: 'v1.61.0'
         args: ./storage/postgresql
 
   integration-and-unit-tests:
@@ -68,4 +68,4 @@ jobs:
 
     - name: Run unit tests
       run: go test -v ./storage/postgresql/... ./quota/postgresqlqm/...
-  
\ No newline at end of file
+  
diff --git a/README.md b/README.md
index 1ad5f708a0..7a3ec98317 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ The current state of feature implementation is recorded in the
 
 To build and test Trillian you need:
 
- - Go 1.22 or later (go 1.22 matches cloudbuild, and is preferred for developers
+ - Go 1.23 or later (go 1.23 matches cloudbuild, and is preferred for developers
    that will be submitting PRs to this project).
 
 To run many of the tests (and production deployment) you need:
diff --git a/go.mod b/go.mod
index b6212bd8fa..1c0955d3f9 100644
--- a/go.mod
+++ b/go.mod
@@ -2,7 +2,7 @@ module github.com/google/trillian
 
 go 1.23.0
 
-toolchain go1.23.6
+toolchain go1.23.4
 
 require (
 	bitbucket.org/creachadair/shell v0.0.8
diff --git a/monitoring/testonly/metrics.go b/monitoring/testonly/metrics.go
index 583d32c7d4..aea5b7a514 100644
--- a/monitoring/testonly/metrics.go
+++ b/monitoring/testonly/metrics.go
@@ -71,7 +71,7 @@ func TestCounter(t *testing.T, factory monitoring.MetricFactory) {
 			// Use a different set of label values
 			// Metrics with different valued label values, are distinct
 			// This test is only applicable when a Metric has labels
-			if test.labelVals != nil && len(test.labelVals) >= 1 {
+			if len(test.labelVals) >= 1 {
 				altLabels := make([]string, len(test.labelVals))
 				copy(altLabels, test.labelVals)
 				altLabels[0] = "alt-val1"
@@ -151,7 +151,7 @@ func TestGauge(t *testing.T, factory monitoring.MetricFactory) {
 			// Use a different set of label values
 			// Metrics with different valued label values, are distinct
 			// This test is only applicable when a Metric has labels
-			if test.labelVals != nil && len(test.labelVals) >= 1 {
+			if len(test.labelVals) >= 1 {
 				altLabels := make([]string, len(test.labelVals))
 				copy(altLabels, test.labelVals)
 				altLabels[0] = "alt-val1"
@@ -223,7 +223,7 @@ func TestHistogram(t *testing.T, factory monitoring.MetricFactory) {
 			// Use a different set of label values
 			// Metrics with different valued label values, are distinct
 			// This test is only applicable when a Metric has labels
-			if test.labelVals != nil && len(test.labelVals) >= 1 {
+			if len(test.labelVals) >= 1 {
 				altLabels := make([]string, len(test.labelVals))
 				copy(altLabels, test.labelVals)
 				altLabels[0] = "alt-val1"
diff --git a/server/errors/errors.go b/server/errors/errors.go
index 3138e0e20f..d2fa45eb78 100644
--- a/server/errors/errors.go
+++ b/server/errors/errors.go
@@ -25,7 +25,7 @@ import (
 // (such as canonical SQL errors), else err is returned unmodified.
 func WrapError(err error) error {
 	if err == sql.ErrNoRows {
-		return status.Errorf(codes.NotFound, err.Error())
+		return status.Error(codes.NotFound, err.Error())
 	}
 
 	return err
diff --git a/server/errors/errors_test.go b/server/errors/errors_test.go
index bbde321851..ced27e06ea 100644
--- a/server/errors/errors_test.go
+++ b/server/errors/errors_test.go
@@ -42,7 +42,7 @@ func TestWrapError(t *testing.T) {
 		},
 		{
 			err:     sql.ErrNoRows,
-			wantErr: status.Errorf(codes.NotFound, sql.ErrNoRows.Error()),
+			wantErr: status.Error(codes.NotFound, sql.ErrNoRows.Error()),
 		},
 	}
 	for _, test := range tests {