teamcapybara/capybara · error · ArgumentError
:cols must be an Array of Arrays
Error message
:cols must be an Array of Arrays
What it means
The :table selector's :cols expression filter describes table contents column-by-column: it expects an Array whose elements are themselves Arrays (one inner array per column; the filter transposes them into rows to build XPath conditions). If any element is not an Array - strings, a flat list, or a nested scalar - the filter raises ArgumentError demanding 'an Array of Arrays'.
Source
Thrown at lib/capybara/selector/definition/table.rb:46
else
cells_xp = col.reduce(nil) do |prev_cell, cell_str|
cell_condition = XPath.string.n.is(cell_str)
if prev_cell
prev_cell = XPath.ancestor(:tr)[1].preceding_sibling(:tr).join(prev_cell)
cell_condition &= (prev_cell & prev_col_position?(prev_cell))
end
XPath.descendant(:td)[cell_condition]
end
XPath.descendant(:tr).join(cells_xp)
end
end.reduce(:&)
xpath[col_conditions]
end
expression_filter(:cols, valid_values: [Array]) do |xpath, cols|
raise ArgumentError, ':cols must be an Array of Arrays' unless cols.all?(Array)
rows = cols.transpose
col_conditions = rows.map { |row| match_row(row, match_size: true) }.reduce(:&)
xpath[match_row_count(rows.size)][col_conditions]
end
expression_filter(:with_rows, valid_values: [Array]) do |xpath, rows|
rows_conditions = rows.map { |row| match_row(row) }.reduce(:&)
xpath[rows_conditions]
end
expression_filter(:rows, valid_values: [Array]) do |xpath, rows|
rows_conditions = rows.map { |row| match_row(row, match_size: true) }.reduce(:&)
xpath[match_row_count(rows.size)][rows_conditions]
end
describe_expression_filters do |caption: nil, **|
" with caption \"#{caption}\"" if captionView on GitHub (pinned to 15b5fdb76e)
Solutions
- Wrap each column in its own array: cols: [%w[Name John], %w[Age 30]] (each inner array is one column's cell contents, top to bottom).
- If your data is row-oriented, use the row-wise filters instead: find(:table, 'Users', rows: [%w[Name Age], %w[John 30]]) or with_rows:.
- For a single column, still nest it: cols: [%w[Total]] or cols: [['Total', 'Sum']].
- Validate fixture-derived structures with cols.all?(Array) (or an arity/type check) before the query so failures point at the data.
Example fix
# before find(:table, 'Users', cols: %w[Name Age]) # after find(:table, 'Users', cols: [%w[Name John], %w[Age 30]])
Defensive patterns
Strategy: validation
Validate before calling
cols = [%w[Name John], %w[Age 30]] raise ArgumentError, ':cols must be an Array of Arrays' unless cols.is_a?(Array) && cols.all?(Array) find(:table, 'Users', cols: cols)
Type guard
def cols_shape?(value) value.is_a?(Array) && value.all?(Array) end
Prevention
- Remember :cols is column-major (each inner array is one column) while :rows/:with_rows are row-major; pick the filter matching your data's orientation.
- Validate fixture-derived table data with cols.all?(Array) before querying so failures point at the data source.
When it happens
Trigger: find(:table, 'Users', cols: %w[Name Age]); find(:table, 'Matrix', cols: 'Name'); find(:table, 'Users', cols: [['Name', 'Age'], 'foo']) - the first two (and the third's last element) fail cols.all?(Array).
Common situations: Passing row-oriented data to :cols by confusing it with the sibling :rows / :with_rows filters (which accept flat inner values row-wise); forgetting the outer wrapping for a single column; generating the structure from JSON/YAML fixtures whose nesting differs.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Invalid option(s) #{invalid_names}, should be one of #{valid
- Invalid option #{match.inspect} for :match, should be one of
- #{@type} is not a valid type for a text query
- redirected more than #{driver.redirect_limit} times, check f
- rack-test requires a rack application, but none was given
AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21).
Data as JSON: /api/errors/186162546560f6c0.
Report an issue: GitHub.