micro/go-micro · warning · ErrNotFound

not found

Error message

not found

What it means

ErrNotFound is the store package's sentinel for a missing key: Get/Read (and the registry helpers built on it) return it when the requested key does not exist in the store. It is a normal, expected outcome for cache-miss style flows, not a crash — the interface contract expects callers to branch on it.

Source

Thrown at store/store.go:14

// Package store is an interface for distributed data storage.
// The design document is located at https://github.com/micro/development/blob/master/design/store.md
package store

import (
	"errors"
	"time"

	"encoding/json"
)

var (
	// ErrNotFound is returned when a key doesn't exist.
	ErrNotFound = errors.New("not found")
	// DefaultStore is the file store (persists to ~/micro/store/).
	DefaultStore Store = NewStore()
)

// Store is a data storage interface.
type Store interface {
	// Init initializes the store. It must perform any required setup on the backing storage implementation and check that it is ready for use, returning any errors.
	Init(...Option) error
	// Options allows you to view the current options.
	Options() Options
	// Read takes a single key name and optional ReadOptions. It returns matching []*Record or an error.
	Read(key string, opts ...ReadOption) ([]*Record, error)
	// Write() writes a record to the store, and returns an error if the record was not written.
	Write(r *Record, opts ...WriteOption) error
	// Delete removes the record with the corresponding key from the store.
	Delete(key string, opts ...DeleteOption) error
	// List returns any keys that match, or an empty list with no error if none matched.
	List(opts ...ListOption) ([]string, error)

View on GitHub (pinned to 24529f1404)

Solutions

  1. Check errors.Is(err, store.ErrNotFound) and treat it as a cache miss: write the record or return a 404-style response
  2. Verify you are reading from the same database/table/namespace the key was written to
  3. If the key should exist, check TTL options passed at Write time and whether another process deleted it

Example fix

// before
recs, err := s.Read("user:42")
if err != nil { return err } // 500 on a simple miss
// after
recs, err := s.Read("user:42")
if err == store.ErrNotFound { return http.StatusNotFound }
if err != nil { return err }
Defensive patterns

Strategy: type-guard

Validate before calling

_, err := st.Read(key)
if err == store.ErrNotFound { /* treat as miss */ }

Type guard

func IsNotFound(err error) bool { return err == store.ErrNotFound || errors.Is(err, store.ErrNotFound) }

Try / catch

recs, err := st.Read(key)
if IsNotFound(err) { return nil, ErrKeyMissing }
if err != nil { return nil, err }

Prevention

When it happens

Trigger: store.Read("key") on a key never written; TestRegistryServiceCheckMissingService path where a service name lookup finds nothing; Load/next iterating a registry/store and exhausting entries.

Common situations: Reading before writing (ordering bug), TTL expiry of a previously written record, wrong database/table/namespace configured so the key lives elsewhere, deleted entries from another process.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/9ab3d8f09e1e5637. Report an issue: GitHub.