micro/go-micro · error
model/postgres: update: %w
Error message
model/postgres: update: %w
What it means
Update builds an UPDATE ... WHERE key = $n statement from the struct's non-key fields and executes it. Any SQL failure is wrapped as "model/postgres: update"; additionally, if the statement succeeds but affects zero rows, the method returns model.ErrNotFound, meaning no record matched the key.
Source
Thrown at model/postgres/postgres.go:141
model.MapToStruct(schema, fields, v)
return nil
}
func (d *postgresModel) Update(ctx context.Context, v interface{}) error {
schema, err := d.schema(v)
if err != nil {
return err
}
fields := model.StructToMap(schema, v)
key := model.KeyValue(schema, v)
setClauses, values := buildUpdate(schema, fields)
values = append(values, key)
paramIdx := len(values)
query := fmt.Sprintf("UPDATE %s SET %s WHERE %s = $%d",
quoteIdent(schema.Table), setClauses, quoteIdent(schema.Key), paramIdx)
result, err := d.db.ExecContext(ctx, query, values...)
if err != nil {
return fmt.Errorf("model/postgres: update: %w", err)
}
n, _ := result.RowsAffected()
if n == 0 {
return model.ErrNotFound
}
return nil
}
func (d *postgresModel) Delete(ctx context.Context, key string, v interface{}) error {
schema, err := d.schema(v)
if err != nil {
return err
}
query := fmt.Sprintf("DELETE FROM %s WHERE %s = $1", quoteIdent(schema.Table), quoteIdent(schema.Key))
result, err := d.db.ExecContext(ctx, query, key)
if err != nil {
return fmt.Errorf("model/postgres: delete: %w", err)
}View on GitHub (pinned to 24529f1404)
Solutions
- Verify the record exists (Read by key) before/after Update; handle model.ErrNotFound for stale IDs.
- Unwrap the error to see the driver's message and fix the offending column/type.
- Ensure the key field is set and matches the stored primary key exactly (type and value).
- Run migrations if the table schema drifted from the model definition.
- Check connectivity and transaction state if the cause is a connection error.
Example fix
// before
if err := store.Update(ctx, &user); err != nil {
return err
}
// after
if err := store.Update(ctx, &user); err != nil {
if errors.Is(err, model.ErrNotFound) {
return http.StatusNotFound
}
return fmt.Errorf("update user %s: %w", user.ID, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// confirm the row exists before Update
var exists bool
if err := db.QueryRow(
"SELECT EXISTS (SELECT 1 FROM users WHERE id = $1)", user.ID,
).Scan(&exists); err != nil {
return err
}
if !exists {
return model.ErrNotFound
} Try / catch
if err := store.Update(ctx, &user); err != nil {
if errors.Is(err, model.ErrNotFound) {
return ErrUserGone // zero rows affected: key doesn't match any row
}
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
log.Printf("update failed [%s]: %s", pgErr.Code, pgErr.Message)
}
return fmt.Errorf("update: %w", err)
} Prevention
- Handle model.ErrNotFound (RowsAffected == 0) explicitly for stale/deleted records.
- Verify the key field is populated and correctly typed before Update.
- Run migrations so the table schema matches the model definition.
- Use optimistic concurrency or re-read on conflict when records may be deleted concurrently.
When it happens
Trigger: Calling postgresModel.Update(ctx, v) where the SQL errors (type mismatch, NOT NULL violation, schema drift, connection issue) — wrapped error; or where the key field of v doesn't match any existing row — ErrNotFound variant.
Common situations: Updating a record that was deleted concurrently, stale client caches holding old IDs, PATCH handlers sending structs with wrong types, or mismatched key type between model schema and table column.
Related errors
- model/postgres: create: %w
- Couldn't create table
- Database connection not initialized
- unsupported statement
- model/postgres: create table: %w
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/355d7dbc942025cf.
Report an issue: GitHub.