From b272e0994ee03424746a4b4cb2fd46478c61362b Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani <45800463+rchincha@users.noreply.github.com> Date: Mon, 11 May 2026 21:25:44 -0700 Subject: [PATCH] fix: downgrade expected missing-blob HEAD logging from error to debug (#4056) Fixes issue #4044 Signed-off-by: Ramkumar Chinchani --- pkg/storage/imagestore/imagestore.go | 8 ++- pkg/storage/local/local_test.go | 86 ++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/pkg/storage/imagestore/imagestore.go b/pkg/storage/imagestore/imagestore.go index c1f75eda..4538e40e 100644 --- a/pkg/storage/imagestore/imagestore.go +++ b/pkg/storage/imagestore/imagestore.go @@ -1605,7 +1605,13 @@ func (is *ImageStore) originalBlobInfo(repo string, digest godigest.Digest) (dri binfo, err := is.storeDriver.Stat(blobPath) if err != nil { - is.log.Error().Err(err).Str("blob", blobPath).Msg("failed to stat blob") + var pathNotFoundErr driver.PathNotFoundError + + if errors.As(err, &pathNotFoundErr) { + is.log.Debug().Err(err).Str("blob", blobPath).Str("digest", digest.String()).Msg("blob not found") + } else { + is.log.Error().Err(err).Str("blob", blobPath).Msg("failed to stat blob") + } return nil, zerr.ErrBlobNotFound } diff --git a/pkg/storage/local/local_test.go b/pkg/storage/local/local_test.go index 3d0fb18b..630016ac 100644 --- a/pkg/storage/local/local_test.go +++ b/pkg/storage/local/local_test.go @@ -893,6 +893,92 @@ func FuzzCheckBlob(f *testing.F) { }) } +func TestMissingBlobChecksDoNotLogErrors(t *testing.T) { + t.Parallel() + + newImageStore := func(t *testing.T) (storageTypes.ImageStore, *bytes.Buffer) { + t.Helper() + + var buf bytes.Buffer + + logger := zlog.NewLoggerWithWriter("debug", &buf) + metrics := monitoring.NewMetricsServer(false, logger) + t.Cleanup(metrics.Stop) + + dir := t.TempDir() + cacheDriver, err := storage.Create("boltdb", cache.BoltDBDriverParameters{ + RootDir: dir, + Name: "cache", + UseRelPaths: true, + }, logger) + if err != nil { + t.Fatalf("create cache driver: %v", err) + } + + imgStore := local.NewImageStore(dir, true, true, logger, metrics, nil, cacheDriver, nil, nil) + + return imgStore, &buf + } + + digest := godigest.FromString("missing-blob") + + t.Run("CheckBlob", func(t *testing.T) { + t.Parallel() + + imgStore, buf := newImageStore(t) + + found, size, err := imgStore.CheckBlob("repo", digest) + if !errors.Is(err, zerr.ErrBlobNotFound) { + t.Fatalf("expected ErrBlobNotFound, got %v", err) + } + + if found { + t.Fatalf("expected missing blob to be absent") + } + + if size != -1 { + t.Fatalf("expected missing blob size -1, got %d", size) + } + + output := buf.String() + if strings.Contains(output, `"level":"error"`) { + t.Fatalf("expected missing blob check to avoid error logs, got %s", output) + } + + if !strings.Contains(output, `"message":"cache miss for blob"`) { + t.Fatalf("expected debug cache-miss log, got %s", output) + } + }) + + t.Run("StatBlob", func(t *testing.T) { + t.Parallel() + + imgStore, buf := newImageStore(t) + + found, size, _, err := imgStore.StatBlob("repo", digest) + if !errors.Is(err, zerr.ErrBlobNotFound) { + t.Fatalf("expected ErrBlobNotFound, got %v", err) + } + + if found { + t.Fatalf("expected missing blob to be absent") + } + + if size != -1 { + t.Fatalf("expected missing blob size -1, got %d", size) + } + + output := buf.String() + if strings.Contains(output, `"level":"error"`) { + t.Fatalf("expected missing blob stat to avoid error logs, got %s", output) + } + + if !strings.Contains(output, `"message":"blob not found"`) { + t.Fatalf("expected debug missing-blob log, got %s", output) + } + }) +} + func FuzzGetBlob(f *testing.F) { f.Fuzz(func(t *testing.T, data string) { log := zlog.NewTestLoggerPtr()