alibaba/DataX · error · ValueError

index must be as long as the number of data rows

Error message

index must be as long as the number of data rows

What it means

ValueError from _prepend_row_index in the vendored tabulate.py used by otsstreamreader's tools: the caller passed an 'index' sequence whose length differs from the number of data rows. tabulate refuses to zip mismatched lengths instead of silently truncating.

Source

Thrown at otsstreamreader/tools/tabulate.py:633

    width += len(header) - visible_width
    if alignment == "left":
        return _padright(width, header)
    elif alignment == "center":
        return _padboth(width, header)
    elif not alignment:
        return "{0}".format(header)
    else:
        return _padleft(width, header)


def _prepend_row_index(rows, index):
    """Add a left-most index column."""
    if index is None or index is False:
        return rows
    if len(index) != len(rows):
        print('index=', index)
        print('rows=', rows)
        raise ValueError('index must be as long as the number of data rows')
    rows = [[v]+list(row) for v,row in zip(index, rows)]
    return rows


def _bool(val):
    "A wrapper around standard bool() which doesn't throw on NumPy arrays"
    try:
        return bool(val)
    except ValueError:  # val is likely to be a numpy array with many elements
        return False


def _normalize_tabular_data(tabular_data, headers, showindex="default"):
    """Transform a supported data type to a list of lists, and a list of headers.

    Supported tabular data types:

    * list-of-lists or another iterable of iterables

View on GitHub (pinned to 80ec23d5c5)

Solutions

  1. Drop the index argument and let tabulate compute/omit it.
  2. Recompute the index after filtering: pass index=range(len(rows)) or the same-length sequence.
  3. Convert the data to a plain list of lists before calling tabulate so only one length source exists.

Example fix

# before
tabulate(rows, headers=cols, index=row_ids)  # row_ids stale after rows = [r for r in rows if ok(r)]
# after
rows = [r for r in rows if ok(r)]
tabulate(rows, headers=cols, index=list(range(len(rows))))
Defensive patterns

Strategy: validation

Validate before calling

if index is not None and len(index) != len(rows):
    raise ValueError('fix caller: index len %d != rows len %d' % (len(index), len(rows)))

Type guard

def index_matches(rows, index):
    return index is None or index is False or len(index) == len(rows)

Prevention

When it happens

Trigger: Calling tabulate(tabular_data, ..., index=seq) where len(seq) != len(rows). With DataFrames tabulate itself derives index = list(df.index), so a mismatch means the object is DataFrame-like but its .values rows count differs from its .index length (pandas version heuristic mismatch).

Common situations: Passing a hand-built index list (e.g. row numbers 0..n-1 computed before filtering rows) alongside data that was filtered afterwards; vendored tabulate (0.7.x era) hitting newer pandas whose .values shape differs; using a DataFrame subclass.

Related errors


AI-assisted analysis of alibaba/DataX@80ec23d5c5 (2026-08-14). Data as JSON: /api/errors/de4e6506f9c2a18c. Report an issue: GitHub.