{"record":{"id":"e1d63a41e8f2768f","repo":"langchain-ai/deepagents","slug":"row-has-len-cells-expected-expected","errorCode":null,"errorMessage":"row has {len} cells, expected {expected}","messagePattern":"row has (.+?) cells, expected (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/app.py","lineNumber":2459,"sourceCode":"    Every header and cell is escaped via `_escape_markdown`, so external text\n    can neither forge additional cells with `|` nor be parsed as markdown.\n\n    Args:\n        headers: Column headings.\n        rows: One sequence of cells per row, each matching `headers` in length.\n\n    Returns:\n        The table as markdown source.\n\n    Raises:\n        ValueError: If a row's length does not match `headers`. Checked because\n            markdown silently drops surplus cells and pads missing ones, so a\n            ragged row would corrupt the table with no other diagnostic.\n    \"\"\"\n    for row in rows:\n        if len(row) != len(headers):\n            msg = f\"row has {len(row)} cells, expected {len(headers)}\"\n            raise ValueError(msg)\n    lines = [\n        \"| \" + \" | \".join(_escape_markdown(header) for header in headers) + \" |\",\n        \"| \" + \" | \".join(\"---\" for _ in headers) + \" |\",\n    ]\n    lines.extend(\n        \"| \" + \" | \".join(_escape_markdown(cell) for cell in row) + \" |\" for row in rows\n    )\n    return \"\\n\".join(lines)\n\n\ndef _log_task_exception(task: asyncio.Task[Any]) -> None:\n    \"\"\"Done-callback that surfaces unhandled exceptions from fire-and-forget tasks.\n\n    Default `asyncio` behavior is to log \"Task exception was never retrieved\"\n    only when the task is GC'd — easy to miss. This callback runs at task\n    completion and routes failures through `logger.warning` with `exc_info`,\n    matching the codebase pattern at `_finalize_git_branch_refresh`. Use\n    when scheduling a coroutine via `asyncio.create_task` whose result is","sourceCodeStart":2441,"sourceCodeEnd":2477,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/app.py#L2441-L2477","documentation":"`_markdown_table` renders rows into a Markdown table and refuses ragged rows: if any row's cell count differs from the header count, it raises this ValueError, because Markdown silently drops surplus cells and pads missing ones — corrupting the table with no diagnostic.","triggerScenarios":"Calling `_markdown_table` (directly or via `_render_extensions` / `_render_tool_catalog`) with a row list whose lengths vary or don't match `len(headers)` — e.g. a source returning a variable-arity tuple per row.","commonSituations":"Extension metadata or tool catalog data where one entry gained/lost a field; joining two data sources with different column counts; optional trailing fields omitted in one row.","solutions":["Pad short rows to the header length and truncate long rows before calling the renderer","Fix the data source so every row has exactly len(headers) cells","Assert row lengths in a unit test when constructing rows dynamically"],"exampleFix":"// before\nrows = [(\"a\", \"b\"), (\"c\",)]\n_markdown_table(headers, rows)\n// after\nrows = [tuple(row) + (\"\",) * (len(headers) - len(row)) if len(row) < len(headers) else row[:len(headers)] for row in rows]\n_markdown_table(headers, rows)","handlingStrategy":"validation","validationCode":"if any(len(row) != len(headers) for row in rows):\n    raise ValueError(\"ragged table rows before rendering\")","typeGuard":"def is_rectangular(headers: list[str], rows: list[list[str]]) -> bool:\n    return all(len(row) == len(headers) for row in rows)","tryCatchPattern":"try:\n    table = _markdown_table(headers, rows)\nexcept ValueError as exc:\n    logger.error(\"table render failed: %s\", exc)\n    table = \"\"  # or fall back to a list rendering","preventionTips":["Normalize rows (pad/truncate) against len(headers) before rendering","Keep data sources producing fixed-width tuples","Add a unit test asserting rectangularity for dynamic catalogs","Check for schema drift when upstream models add/remove fields"],"tags":["markdown","rendering","data-shape"],"backgroundTag":"ragged-table-row","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}