{"record":{"id":"303df879c9469fc9","repo":"benbjohnson/litestream","slug":"prepare-statement-w","errorCode":null,"errorMessage":"prepare statement: %w","messagePattern":"prepare statement: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream-test/populate.go","lineNumber":186,"sourceCode":"\treturn nil\n}\n\nfunc (c *PopulateCommand) populateTable(ctx context.Context, db *sql.DB, tableName string, rowCount int) error {\n\tdata := make([]byte, c.RowSize)\n\n\tfor i := 0; i < rowCount; i += c.BatchSize {\n\t\ttx, err := db.Begin()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"begin transaction: %w\", err)\n\t\t}\n\n\t\tstmt, err := tx.Prepare(fmt.Sprintf(`\n\t\t\tINSERT INTO %s (data, text_field, int_field, float_field, timestamp)\n\t\t\tVALUES (?, ?, ?, ?, ?)\n\t\t`, tableName))\n\t\tif err != nil {\n\t\t\ttx.Rollback()\n\t\t\treturn fmt.Errorf(\"prepare statement: %w\", err)\n\t\t}\n\n\t\tbatchEnd := i + c.BatchSize\n\t\tif batchEnd > rowCount {\n\t\t\tbatchEnd = rowCount\n\t\t}\n\n\t\tfor j := i; j < batchEnd; j++ {\n\t\t\tcryptorand.Read(data)\n\t\t\ttextField := fmt.Sprintf(\"row_%d_%d\", i, j)\n\t\t\tintField := rand.Int63()\n\t\t\tfloatField := rand.Float64() * 1000\n\t\t\ttimestamp := time.Now().Unix()\n\n\t\t\tif _, err := stmt.Exec(data, textField, intField, floatField, timestamp); err != nil {\n\t\t\t\tstmt.Close()\n\t\t\t\ttx.Rollback()\n\t\t\t\treturn fmt.Errorf(\"insert row: %w\", err)","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream-test/populate.go#L168-L204","documentation":"populateTable wraps a failed tx.Prepare of the batch INSERT statement in this error. The statement inserts data, text_field, int_field, float_field and timestamp for each row in the batch. On failure the transaction is rolled back first, then this error is returned, so no partial batch rows remain.","triggerScenarios":"tx.Prepare(...) fails: SQL syntax error from a malformed table name interpolated into the statement, the table or its columns do not exist (schema drift), or the driver cannot allocate a statement handle.","commonSituations":"Re-running against a database whose tables were created by a different schema version; a table name containing characters that break the interpolated SQL; driver/connection state corrupted after a previous error.","solutions":["Confirm the table was created with the expected columns (data, text_field, int_field, float_field, timestamp).","Check the table name is a plain identifier (test_table_N); re-create the database if it was made by an older version.","Read the wrapped SQLite error for 'no such table'/'no such column' hints.","Roll back as the code already does, then retry from a clean database if schema is suspect."],"exampleFix":"// before\nstmt, err := tx.Prepare(fmt.Sprintf(\"INSERT INTO %s (...) VALUES (...)\", tableName))\n// after\nif err != nil {\n    tx.Rollback()\n    return fmt.Errorf(\"prepare statement for %s: %w\", tableName, err) // surface table name for diagnosis\n}","handlingStrategy":"validation","validationCode":"// verify table/columns exist before preparing the insert\nrows, err := db.Query(fmt.Sprintf(\"PRAGMA table_info(%s)\", tableName))\nif err != nil {\n    return err\n}\ndefer rows.Close()\nrequired := map[string]bool{\"data\": false, \"text_field\": false, \"int_field\": false, \"float_field\": false, \"timestamp\": false}\nfor rows.Next() {\n    var cid int; var name, typ string; var notNull, pk int\n    if err := rows.Scan(&cid, &name, &typ, &notNull, &pk); err == nil {\n        if _, ok := required[name]; ok { required[name] = true }\n    }\n}\nfor col, ok := range required {\n    if !ok { return fmt.Errorf(\"table %s missing column %s\", tableName, col) }\n}","typeGuard":null,"tryCatchPattern":"stmt, err := tx.Prepare(insertSQL)\nif err != nil {\n    tx.Rollback()\n    return fmt.Errorf(\"prepare statement: %w\", err)\n}","preventionTips":["Always create tables in the same run that inserts into them.","Keep table names as plain identifiers (test_table_N).","Roll back the transaction on prepare failure (the code already does this).","Verify schema with PRAGMA table_info when reusing existing databases."],"tags":["sqlite","prepared-statement","database"],"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"}