{"record":{"id":"0873455a7aa2c310","repo":"benbjohnson/litestream","slug":"count-rows-w","errorCode":null,"errorMessage":"count rows: %w","messagePattern":"count rows: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream-test/shrink.go","lineNumber":175,"sourceCode":"\tdefer rows.Close()\n\n\tvar tables []string\n\tfor rows.Next() {\n\t\tvar table string\n\t\tif err := rows.Scan(&table); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ttables = append(tables, table)\n\t}\n\n\treturn tables, nil\n}\n\nfunc (c *ShrinkCommand) deleteFromTable(db *sql.DB, table string) (int64, error) {\n\tvar totalRows int\n\tcountQuery := fmt.Sprintf(\"SELECT COUNT(*) FROM %s\", table)\n\tif err := db.QueryRow(countQuery).Scan(&totalRows); err != nil {\n\t\treturn 0, fmt.Errorf(\"count rows: %w\", err)\n\t}\n\n\tif totalRows == 0 {\n\t\treturn 0, nil\n\t}\n\n\trowsToDelete := int(float64(totalRows) * (c.DeletePercentage / 100))\n\tif rowsToDelete == 0 {\n\t\treturn 0, nil\n\t}\n\n\tvar hasID bool\n\tcolumnQuery := fmt.Sprintf(\"PRAGMA table_info(%s)\", table)\n\trows, err := db.Query(columnQuery)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"get table info: %w\", err)\n\t}\n\tdefer rows.Close()","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream-test/shrink.go#L157-L193","documentation":"This error wraps the failure of a `SELECT COUNT(*)` query against a table whose name was interpolated directly into SQL by the shrink test tool. It means the underlying SQLite driver could not execute the count query — usually a syntax error (bad table name) or the table does not exist. It is thrown by `ShrinkCommand.deleteFromTable` so the caller (`shrinkDatabase`) can abort before attempting row deletion.","triggerScenarios":"Calling `litestream-test shrink` with a table name that does not exist in the source database; table name containing characters that break SQL interpolation; database file locked or unreadable by another process; database corrupted so the count scan fails.","commonSituations":"Testing shrink on a database where the target table was dropped or renamed; passing a quoted or schema-qualified table name (e.g. `main.t`) that the naive `fmt.Sprintf(\"SELECT COUNT(*) FROM %s\")` mishandles; the DB file path points to an empty/nonexistent file where SQLite creates an empty DB with no tables.","solutions":["Verify the table name exists: `sqlite3 <db> '.tables'` and pass the exact name","Run the shrink with an unlocked database (close other litestream/SQLite connections)","Check the error wrapped by %w (`sqlite: no such table: ...`) for the actual SQL failure cause","Re-create or restore the database if corruption is reported"],"exampleFix":"// before\ncountQuery := fmt.Sprintf(\"SELECT COUNT(*) FROM %s\", table)\n// after\n// verify table exists first, e.g. via PRAGMA table_list, and use a quoted identifier\ncountQuery := fmt.Sprintf(\"SELECT COUNT(*) FROM %q\", table)","handlingStrategy":"validation","validationCode":"var exists int\nerr := db.QueryRow(\"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?\", table).Scan(&exists)\nif err != nil || exists == 0 { return fmt.Errorf(\"table %q not found\", table) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check table existence in sqlite_master before shrink","Quote identifiers interpolated into SQL","Keep the source DB closed to other writers during shrink"],"tags":["sqlite","sql","database","test-tooling"],"backgroundTag":"database-query-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}