micro/go-micro · error
sqlStore.read failed
Error message
sqlStore.read failed
What it means
The legacy postgres store's read function executes the query (exact key or pattern) and wraps failures with 'sqlStore.read failed'. sql.ErrNoRows is treated as an empty result, so this error means the query itself failed, not that the key is missing. Callers: Read (single-key reads).
Source
Thrown at store/postgres/postgres.go:475
return nil, err
}
defer st.Close()
rows, err = st.Query(pattern, options.Limit, options.Offset)
} else {
st, err = s.prepare(options.Database, options.Table, "readMany")
if err != nil {
return nil, err
}
defer st.Close()
rows, err = st.Query(pattern)
}
if err != nil {
if err == sql.ErrNoRows {
return []*store.Record{}, nil
}
return []*store.Record{}, errors.Wrap(err, "sqlStore.read failed")
}
defer rows.Close()
records, err := s.rowsToRecords(rows)
if err != nil {
return nil, err
}
rowErr := rows.Close()
if rowErr != nil {
// transaction rollback or something
return records, rowErr
}
if err := rows.Err(); err != nil {
return records, err
}
return records, nilView on GitHub (pinned to 24529f1404)
Solutions
- Check the wrapped driver error for the root cause (connection vs syntax vs timeout).
- Confirm the table exists and the store was initialized against the right database.
- Retry on transient connection errors; enable connection health checks (db.SetConnMaxLifetime).
- Validate/escape keys used in pattern queries.
- Verify read privileges on the table for the DB user.
Example fix
// before
recs, err := s.Read("user:1; DROP") // unsafe pattern chars
// after
if !validKeyPattern(key) { return nil, ErrInvalidKey }
recs, err := s.Read(key) Defensive patterns
Strategy: retry
Validate before calling
// before read
if key == "" { return ErrEmptyKey }
if strings.ContainsAny(key, "%'\\;") { return ErrInvalidKeyPattern }
if err := db.Ping(); err != nil { // refresh connection } Type guard
func isReadErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "sqlStore.read failed") && !errors.Is(err, sql.ErrNoRows)
} Try / catch
recs, err := store.Read(key)
if err != nil {
if isTransientNetErr(err) {
return retryWithBackoff(func() error { _, err = store.Read(key); return err })
}
return err // missing keys return empty slice + nil, not this error
} Prevention
- Treat empty results (nil error) as key-not-found; only transient/network failures need retries.
- Validate/escape keys used in pattern reads.
- Set ConnMaxLifetime so stale pooled connections are recycled.
- Ensure the store schema exists and wasn't dropped out-of-band.
- Set a sane statement_timeout and handle it explicitly.
When it happens
Trigger: Calling store.Read with a key when the SELECT fails: connection errors, table missing (initialization skipped or dropped), invalid SQL pattern characters, statement timeouts, or rowsToRecords scanning issues after query execution.
Common situations: Database restarted or connection pool stale; schema changed out-of-band (table dropped); special characters in keys breaking LIKE patterns; long queries hitting statement_timeout on managed Postgres.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- unsupported statement
- model/postgres: create: %w
- model/postgres: update: %w
- cannot create table
- cannot create metadata index
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/cd6fd9d49ecf1b6a.
Report an issue: GitHub.