googleapis/mcp-toolbox · warning
unable to get rows affected: %w
Error message
unable to get rows affected: %w
What it means
Returned by Source.RunSQL after a successful DML ExecContext when result.RowsAffected() fails to report how many rows the statement modified. The statement itself executed; only the row-count retrieval from the driver failed. This is rare with Oracle drivers but occurs when the driver cannot provide affected-row counts for the executed statement type.
Source
Thrown at internal/sources/oracle/oracle.go:154
func (s *Source) ToConfig() sources.SourceConfig {
return s.Config
}
func (s *Source) OracleDB() *sql.DB {
return s.DB
}
func (s *Source) RunSQL(ctx context.Context, statement string, params []any, readOnly bool) (any, error) {
if !readOnly {
result, err := s.OracleDB().ExecContext(ctx, statement, params...)
if err != nil {
return nil, fmt.Errorf("unable to execute DML statement: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return nil, fmt.Errorf("unable to get rows affected: %w", err)
}
return map[string]any{
"status": "success",
"rows_affected": rowsAffected,
}, nil
}
rows, err := s.OracleDB().QueryContext(ctx, statement, params...)
if err != nil {
return nil, fmt.Errorf("unable to execute query: %w", err)
}
defer rows.Close()
// If Columns() errors, it might be a DDL/DML without an OUTPUT clause.
// We proceed, and results.Err() will catch actual query execution errors.
// 'out' will remain an empty slice if cols is empty or err is not nil here.
cols, _ := rows.Columns()
View on GitHub (pinned to 8cc6e09de2)
Solutions
- Check the wrapped driver error to see which statement form caused it.
- Use plain DML (INSERT/UPDATE/DELETE/MERGE) through this path; run DDL/PL-SQL outside the tool or accept that row counts are undefined.
- Upgrade the go-ora or godror driver version, as row-count support for statement types has improved over releases.
- If the statement genuinely succeeded, treat the operation as applied and re-run only the count via an explicit query if needed.
Example fix
// before (DDL through DML path → rows affected undefined) statement: "TRUNCATE TABLE audit_log" // after (query the count instead, or execute DDL outside the tool) statement: "DELETE FROM audit_log WHERE log_date < SYSDATE - 90"
Defensive patterns
Strategy: fallback
Validate before calling
// avoid DDL/PL-SQL on the DML path; detect statement kinds that have no row count
func hasRowsAffectedSemantics(stmt string) bool {
s := strings.ToUpper(strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(stmt), ";")))
for _, kw := range []string{"INSERT", "UPDATE", "DELETE", "MERGE"} {
if strings.HasPrefix(s, kw+" ") {
return true
}
}
return false
} Type guard
func isRowsAffectedError(err error) bool {
return err != nil && strings.Contains(err.Error(), "unable to get rows affected")
} Try / catch
res, err := src.RunSQL(ctx, stmt, params, false)
if err != nil {
if isRowsAffectedError(err) {
log.Printf("statement likely applied but row count unavailable: %v", err)
return map[string]any{"status": "success", "rows_affected": nil}, nil
}
return err
} Prevention
- Restrict the execute-sql tool to INSERT/UPDATE/DELETE/MERGE statements where row counts are defined.
- Run DDL and anonymous PL/SQL blocks outside this tool path.
- Pin and periodically update go-ora/godror driver versions for better row-count support.
When it happens
Trigger: readOnly=false path of RunSQL: ExecContext succeeds but result.RowsAffected() returns an error — typically for statements where the driver cannot compute affected rows (e.g. certain PL/SQL blocks, DDL statements like CREATE/DROP executed via ExecContext), or a driver-specific internal failure.
Common situations: Executing DDL (CREATE TABLE, TRUNCATE) or anonymous PL/SQL blocks through the execute-sql tool where affected-row semantics are undefined; unusual statement types that the go-ora/godror driver cannot map to a row count.
Related errors
- unable to execute DML statement: %w
- unable to execute query: %w
- unable to execute query: %w
- unable to parse row: %w
- unable to create driver: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/ac27478113996627.
Report an issue: GitHub.