{"record":{"id":"79f02e38539971f6","repo":"dbt-labs/dbt-core","slug":"table-join-right-table-must-be-a-table-right-ta","errorCode":null,"errorMessage":"Table.join: right_table must be a Table: {right_table} found instead","messagePattern":"Table\\.join: right_table must be a Table: (.+?) found instead","errorType":"validation","errorClass":"InvalidArgument","httpStatus":null,"severity":"error","filePath":"crates/dbt-agate/src/table.rs","lineNumber":1297,"sourceCode":"            \"join\" => {\n                let iter = ArgsIter::new(\"Table.join\", &[\"right_table\"], args);\n                let right_table = iter.next_arg::<&Value>()?;\n                let left_key = iter.next_kwarg::<Option<&Value>>(\"left_key\")?;\n                let right_key = iter.next_kwarg::<Option<&Value>>(\"right_key\")?;\n                let inner = iter.next_kwarg::<Option<bool>>(\"inner\")?.unwrap_or(false);\n                let full_outer = iter\n                    .next_kwarg::<Option<bool>>(\"full_outer\")?\n                    .unwrap_or(false);\n                let require_match = iter\n                    .next_kwarg::<Option<bool>>(\"require_match\")?\n                    .unwrap_or(false);\n                let columns = iter.next_kwarg::<Option<&Value>>(\"columns\")?;\n                iter.finish()?;\n\n                let right_table = match right_table.downcast_object_ref::<AgateTable>() {\n                    Some(table) => table,\n                    None => {\n                        return Err(Error::new(\n                            ErrorKind::InvalidArgument,\n                            format!(\n                                \"Table.join: right_table must be a Table: {right_table} found instead\"\n                            ),\n                        ));\n                    }\n                };\n\n                let join_type = if inner {\n                    if full_outer {\n                        return Err(Error::new(\n                            ErrorKind::InvalidArgument,\n                            \"A join can not be both \\\"inner\\\" and \\\"full_outer\\\".\",\n                        ));\n                    }\n                    JoinType::Inner\n                } else if full_outer {\n                    JoinType::FullOuter","sourceCodeStart":1279,"sourceCodeEnd":1315,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-agate/src/table.rs#L1279-L1315","documentation":"Thrown by `Table.join()` when the `right_table` argument is not an AgateTable object. The method downcasts the passed Value to an AgateTable reference, and if the downcast fails it raises this InvalidArgument error. Both operands of a join must be Table instances.","triggerScenarios":"Calling `table.join(x, ...)` where `x` is a TableSet, a dict, a list of rows, or any non-Table value instead of an agate Table.","commonSituations":"Passing the result of `table.group_by(...)` (a TableSet) to join by mistake; passing raw data structures that were never constructed into a Table; variable shadowing where the right table variable was reassigned.","solutions":["Ensure the right operand is an agate Table constructed via Table(...)","If you have a TableSet, select the specific table first, e.g. `table_set['name']`","Check for variable shadowing/reassignment of the right_table variable","Print `type(right_table)` before the join to confirm"],"exampleFix":"// before\ntable.join(table.group_by('k'), 'k')  # TableSet, not Table\n// after\njoined = table.join(other_table, 'k')","handlingStrategy":"type-guard","validationCode":"if not isinstance(right, agate.Table):\n    raise TypeError(f'right_table must be a Table, got {type(right).__name__}')","typeGuard":"def is_agate_table(v):\n    return isinstance(v, agate.Table)","tryCatchPattern":"try:\n    joined = table.join(right, 'k')\nexcept Exception as e:\n    if 'right_table must be a Table' in str(e):\n        raise TypeError('join requires an agate.Table as right_table') from e\n    raise","preventionTips":["Never pass a TableSet where a Table is expected","Check variable provenance before joins","Use type hints/linters to catch non-Table arguments"],"tags":["rust","type-error","argument-validation"],"backgroundTag":"type-mismatch","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}