dbt-labs/dbt-core · error · InvalidArgument
A join can not be both "inner" and "full_outer".
Error message
A join can not be both "inner" and "full_outer".
What it means
Thrown by `Table.join()` when both `inner=True` and `full_outer=True` are passed. These join types are mutually exclusive — a join is either an inner join or a full outer join, not both — so the library raises this InvalidArgument error before performing the join.
Source
Thrown at crates/dbt-agate/src/table.rs:1308
.unwrap_or(false);
let columns = iter.next_kwarg::<Option<&Value>>("columns")?;
iter.finish()?;
let right_table = match right_table.downcast_object_ref::<AgateTable>() {
Some(table) => table,
None => {
return Err(Error::new(
ErrorKind::InvalidArgument,
format!(
"Table.join: right_table must be a Table: {right_table} found instead"
),
));
}
};
let join_type = if inner {
if full_outer {
return Err(Error::new(
ErrorKind::InvalidArgument,
"A join can not be both \"inner\" and \"full_outer\".",
));
}
JoinType::Inner
} else if full_outer {
JoinType::FullOuter
} else {
JoinType::LeftOuter
};
let table = self.join(
right_table,
left_key,
right_key,
join_type,
require_match,
columns,View on GitHub (pinned to 0267ce9170)
Solutions
- Pass only one of `inner` or `full_outer` as True
- Omit both flags for the default join behavior
- Add validation in calling code that rejects conflicting join options
- If you need a different join type, check the supported JoinType variants (inner, full_outer) and pick one
Example fix
// before table.join(right, 'k', 'k', inner=True, full_outer=True) // after table.join(right, 'k', 'k', inner=True) # or full_outer=True, not both
Defensive patterns
Strategy: validation
Validate before calling
if inner and full_outer:
raise ValueError('inner and full_outer are mutually exclusive') Type guard
null
Try / catch
try:
joined = table.join(right, lk, rk, inner=inner, full_outer=full_outer)
except Exception as e:
if 'can not be both' in str(e):
raise ValueError('choose either inner or full_outer') from e
raise Prevention
- Build join flags from a single mutually exclusive enum/option
- Never set both boolean join flags from user config without a check
- Remember the default join is already inner
When it happens
Trigger: Calling `table.join(right, left_key, right_key, inner=True, full_outer=True)`, typically from code that builds join flags dynamically and sets both booleans.
Common situations: Programmatic join construction where flags accumulate from config or user options without a mutual-exclusion check; misunderstanding the boolean API (default join is already inner).
Understand the failure class
Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.
Related errors
- Table.select: key must be a string or an array of strings: {
- Table.select: key must be a string or an array of strings: {
- Table.join: right_table must be a Table: {right_table} found
- Table.limit: {e}
- Table.distinct: {e}
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/faa94f240158579f.
Report an issue: GitHub.