{"record":{"id":"cd6fd9d49ecf1b6a","repo":"micro/go-micro","slug":"sqlstore-read-failed","errorCode":null,"errorMessage":"sqlStore.read failed","messagePattern":"sqlStore\\.read failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/postgres/postgres.go","lineNumber":475,"sourceCode":"\t\t\treturn nil, err\n\t\t}\n\t\tdefer st.Close()\n\n\t\trows, err = st.Query(pattern, options.Limit, options.Offset)\n\t} else {\n\t\tst, err = s.prepare(options.Database, options.Table, \"readMany\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefer st.Close()\n\n\t\trows, err = st.Query(pattern)\n\t}\n\tif err != nil {\n\t\tif err == sql.ErrNoRows {\n\t\t\treturn []*store.Record{}, nil\n\t\t}\n\t\treturn []*store.Record{}, errors.Wrap(err, \"sqlStore.read failed\")\n\t}\n\n\tdefer rows.Close()\n\n\trecords, err := s.rowsToRecords(rows)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\trowErr := rows.Close()\n\tif rowErr != nil {\n\t\t// transaction rollback or something\n\t\treturn records, rowErr\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn records, err\n\t}\n\n\treturn records, nil","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/store/postgres/postgres.go#L457-L493","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nrecs, err := s.Read(\"user:1; DROP\") // unsafe pattern chars\n// after\nif !validKeyPattern(key) { return nil, ErrInvalidKey }\nrecs, err := s.Read(key)","handlingStrategy":"retry","validationCode":"// before read\nif key == \"\" { return ErrEmptyKey }\nif strings.ContainsAny(key, \"%'\\\\;\") { return ErrInvalidKeyPattern }\nif err := db.Ping(); err != nil { // refresh connection }","typeGuard":"func isReadErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"sqlStore.read failed\") && !errors.Is(err, sql.ErrNoRows)\n}","tryCatchPattern":"recs, err := store.Read(key)\nif err != nil {\n\tif isTransientNetErr(err) {\n\t\treturn retryWithBackoff(func() error { _, err = store.Read(key); return err })\n\t}\n\treturn err // missing keys return empty slice + nil, not this error\n}","preventionTips":["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."],"tags":["postgres","sql","read","query"],"backgroundTag":"sql-query-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}