cocoindex-io/cocoindex · error
row_count must be positive
Error message
row_count must be positive
What it means
Raised by _delete_sql in the BigQuery connector when asked to build a DELETE statement for a non-positive number of rows. The generated SQL uses one positional query parameter (@p0, @p1, ...) per row to delete, so row_count must be at least 1; 0 or negative means the caller computed an empty or invalid batch.
Source
Thrown at python/cocoindex/connectors/bigquery/_target.py:314
f"ON {on_clause}",
]
if non_pk_cols:
update_list = ", ".join(f"`{c}` = source.`{c}`" for c in non_pk_cols)
sql_parts.append(f"WHEN MATCHED THEN UPDATE SET {update_list}")
sql_parts.append(
f"WHEN NOT MATCHED THEN INSERT ({insert_cols}) VALUES ({insert_values})"
)
return " ".join(sql_parts)
def _delete_sql(
qualified_table_name: str, table_schema: TableSchema[Any], *, row_count: int
) -> str:
pk_cols = table_schema.primary_key
if row_count <= 0:
raise ValueError("row_count must be positive")
if len(pk_cols) == 1:
markers = ", ".join(f"@p{i}" for i in range(row_count))
return f"DELETE FROM {qualified_table_name} WHERE `{pk_cols[0]}` IN ({markers})"
row_clauses = []
param_idx = 0
for _ in range(row_count):
and_parts = []
for pk in pk_cols:
and_parts.append(f"`{pk}` = @p{param_idx}")
param_idx += 1
row_clauses.append(f"({' AND '.join(and_parts)})")
return f"DELETE FROM {qualified_table_name} WHERE {' OR '.join(row_clauses)}"
def _encode_value(col: ColumnDef, value: Any) -> Any:
if value is None:View on GitHub (pinned to e84aa99b32)
Solutions
- Ensure the caller skips the DELETE entirely when the batch is empty (guard with `if row_count > 0` before calling _delete_sql).
- Check what feeds row_count in _apply_actions — inspect why an empty or negative key batch reached the delete path.
- Report/fix the batching bug if a non-empty action list yields row_count<=0.
Example fix
// before
sql = _delete_sql(qualified, schema, row_count=len(keys))
// after
if keys:
sql = _delete_sql(qualified, schema, row_count=len(keys)) Defensive patterns
Strategy: validation
Validate before calling
if not keys:
return # or skip building the DELETE
assert len(keys) > 0, "delete batch must be non-empty" Prevention
- Guard delete paths with `if batch:` before generating SQL
- Keep batching logic in one place so empty batches are skipped consistently
- Add a unit test for the empty-batch case
When it happens
Trigger: Calling _delete_sql (via _apply_actions during a target sync) with row_count=0 or negative, e.g. when a delete batch contains no primary keys but the delete path is still invoked.
Common situations: A sync run where all declared rows were removed and an empty delete batch is generated; bugs in batching logic that pass len(keys)=0; upstream code changes that no longer guard against empty batches.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Expected at least one input argument
- Batching and runner require the function to be async. Use @c
- Async functions are not supported by @coco.fn decorator when
- Primary key column '{pk}' not found in columns: {list(self.c
- record_type must be a record type (dataclass, NamedTuple, Py
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/f43a54745b61f2b9.
Report an issue: GitHub.