micro/go-micro · error
ErrDuplicateKey
ErrDuplicateKey
Error message
duplicate key
What it means
model.ErrDuplicateKey is returned when creating a record whose primary key already exists in the store. The model package enforces key uniqueness on Create and surfaces this sentinel so callers can detect conflicts.
Source
Thrown at model/model.go:13
// Package model is an interface for structured data storage with schema awareness.
package model
import (
"context"
"errors"
)
var (
// ErrNotFound is returned when a record doesn't exist.
ErrNotFound = errors.New("not found")
// ErrDuplicateKey is returned when a record with the same key already exists.
ErrDuplicateKey = errors.New("duplicate key")
// ErrNotRegistered is returned when a table has not been registered.
ErrNotRegistered = errors.New("table not registered")
// DefaultModel is the default model.
DefaultModel Model = NewModel()
)
// Model is a structured data storage interface.
type Model interface {
// Init initializes the model.
Init(...Option) error
// Register registers a struct type as a table.
Register(v interface{}, opts ...RegisterOption) error
// Create inserts a new record. Returns ErrDuplicateKey if key exists.
Create(ctx context.Context, v interface{}) error
// Read retrieves a record by key into v. Returns ErrNotFound if missing.
Read(ctx context.Context, key string, v interface{}) error
// Update modifies an existing record. Returns ErrNotFound if missing.
Update(ctx context.Context, v interface{}) errorView on GitHub (pinned to 24529f1404)
Solutions
- Check errors.Is(err, model.ErrDuplicateKey) and treat it as upsert/already-exists where appropriate.
- Delete the existing record first or use an update/replace path instead of Create.
- Add a unique client/node ID (node.Id) to the key so concurrent registrars don't collide.
- Clean the store between test runs to avoid leftovers triggering duplicates.
Example fix
// before
err := m.Create("services", rec) // fails if key exists
// after
err := m.Create("services", rec)
if errors.Is(err, model.ErrDuplicateKey) {
err = m.Update("services", rec)
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
func isDuplicate(err error) bool { return errors.Is(err, model.ErrDuplicateKey) } Try / catch
err := m.Create("services", rec)
if errors.Is(err, model.ErrDuplicateKey) {
return m.Update("services", rec) // upsert semantics
}
return err Prevention
- Include a unique node/client ID in record keys
- Check existence (or delete) before Create when idempotency matters
- Clean the store between test runs
- Serialize registration under a leader/lock when multiple instances may race
When it happens
Trigger: Calling Create twice with the same service name/key without deleting the first; two nodes racing to register the same key concurrently; re-running an idempotent-by-intent registration that isn't actually idempotent.
Common situations: Restart loops re-registering services; leader-election code where two instances briefly both act as leader; test suites not cleaning the store between runs.
Related errors
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/d05bd36bfa8dc90d.
Report an issue: GitHub.