t8y2/dbx · error

checked length

Error message

checked length

What it means

join_condition_clauses in the DynamoDB query builder collapses a list of ConditionClauses with an AND/OR operator. When exactly one clause is present it short-circuits with clauses.into_iter().next().expect("checked length"); the expect is protected by the len()==1 check directly above and panics only if that guard is removed or reordered.

Source

Thrown at crates/dbx-core/src/db/dynamodb_driver.rs:287

                        .and_then(|object| object.get("$regex"))
                        .and_then(Value::as_str)
                        .ok_or_else(|| format!("Unsupported DynamoDB $not condition for {field}"))?;
                    format!("NOT contains({path}, {})", self.value(&Value::String(nested.to_string()))?)
                }
                other => return Err(format!("Unsupported DynamoDB filter operator: {other}")),
            };
            clauses.push(clause);
        }
        if clauses.is_empty() {
            return Err(format!("DynamoDB filter for {field} does not contain a condition"));
        }
        Ok(clauses.join(" AND "))
    }
}

fn join_condition_clauses(clauses: Vec<ConditionClause>, operator: &str, precedence: u8) -> ConditionClause {
    if clauses.len() == 1 {
        return clauses.into_iter().next().expect("checked length");
    }
    let expression = clauses
        .into_iter()
        .map(
            |clause| {
                if clause.precedence < precedence {
                    format!("({})", clause.expression)
                } else {
                    clause.expression
                }
            },
        )
        .collect::<Vec<_>>()
        .join(operator);
    ConditionClause { expression, precedence }
}

pub fn endpoint_url(config: &ConnectionConfig, host: &str, port: u16) -> String {

View on GitHub (pinned to c0390bff16)

Solutions

  1. Keep the len()==1 guard immediately before extraction; prefer `let Some(clause) = clauses.into_iter().next() else { ... }`.
  2. Handle the empty-vec case explicitly (return a trivially-true clause or error) so the join never sees unexpected lengths.
  3. Add a unit test joining 0, 1, and 2+ clauses to lock the behavior.
  4. If panics are unacceptable in the query builder, switch join_condition_clauses to return Result<ConditionClause, String>.

Example fix

// before
if clauses.len() == 1 {
    return clauses.into_iter().next().expect("checked length");
}
// after
if let Some(single) = clauses.into_iter().next() {
    if matches!(clauses_len_hint, 1) { return single; }
}
// or simpler:
if clauses.len() == 1 {
    return match clauses.into_iter().next() { Some(c) => c, None => return trivially_true_clause() };
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before joining condition clauses, handle degenerate lengths
if clauses.is_empty() { return Ok(default_clause()); } // skip join entirely

Type guard

fn single_clause(clauses: Vec<ConditionClause>) -> Option<ConditionClause> {
    if clauses.len() == 1 { clauses.into_iter().next() } else { None }
}

Try / catch

if clauses.len() == 1 {
    return match clauses.into_iter().next() {
        Some(c) => c,
        None => return default_clause(),
    };
}

Prevention

When it happens

Trigger: Unreachable while `if clauses.len() == 1` precedes the into_iter().next(); a panic would indicate a refactor dropped the guard. Users never see this panic — with zero clauses callers skip joining, and with multiple clauses the code falls through to parenthesized combination.

Common situations: Builders constructing DynamoDB filter expressions from key conditions, filter expressions, or user query predicates; library maintainers refactoring condition_clause/join_condition_clauses; automated tests feeding single-condition queries (e.g. one equality key condition).

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/db0bdfc65943c05f. Report an issue: GitHub.