t8y2/dbx · error

validated DynamoDB insert key

Error message

validated DynamoDB insert key

What it means

This is a Rust panic from `Option::expect` on `statement.key` when serializing the key for a DynamoDB Insert statement. The library assumes an earlier validation/parse step guaranteed a key exists for inserts; if it is None, the invariant is broken and the process panics instead of returning a typed error. It signals an internal contract violation between statement parsing/validation and execution, not a user-facing DynamoDB failure.

Source

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

            let requested_limit = statement.limit.unwrap_or(max_rows.max(1).min(MAX_PAGE_SIZE as usize) as i64);
            let effective_limit = requested_limit.min(max_rows.max(1).min(i64::MAX as usize) as i64);
            let filter =
                statement.filter.as_ref().map(serde_json::to_string).transpose().map_err(|error| error.to_string())?;
            let sort =
                statement.sort.as_ref().map(serde_json::to_string).transpose().map_err(|error| error.to_string())?;
            let result = find_items(
                client,
                &statement.table,
                effective_limit,
                filter.as_deref(),
                sort.as_deref(),
                statement.cursor.as_deref(),
            )
            .await?;
            Ok(document_query_result(result, started))
        }
        DynamoDbStatementOperation::Insert => {
            let key = serde_json::to_string(statement.key.as_ref().expect("validated DynamoDB insert key"))
                .map_err(|error| error.to_string())?;
            let item = serde_json::to_string(statement.item.as_ref().expect("validated DynamoDB insert item"))
                .map_err(|error| error.to_string())?;
            insert_item_with_expected_identity(client, &statement.table, &item, Some(&key)).await?;
            Ok(affected_query_result(1, started))
        }
        DynamoDbStatementOperation::Put => {
            let key = serde_json::to_string(statement.key.as_ref().expect("validated DynamoDB put key"))
                .map_err(|error| error.to_string())?;
            let item = serde_json::to_string(statement.item.as_ref().expect("validated DynamoDB put item"))
                .map_err(|error| error.to_string())?;
            let affected = update_item(client, &statement.table, &key, &item).await?;
            Ok(affected_query_result(affected, started))
        }
        DynamoDbStatementOperation::Delete => {
            let key = serde_json::to_string(statement.key.as_ref().expect("validated DynamoDB delete key"))
                .map_err(|error| error.to_string())?;
            let affected = delete_item(client, &statement.table, &key).await?;

View on GitHub (pinned to c0390bff16)

Solutions

  1. Always construct DynamoDB insert statements through parse_dynamodb_statement so the explicit-key validation runs before execute_statement
  2. Before calling execute_statement for Insert, check statement.key.is_some() and return a proper error if absent
  3. Replace the expect with .ok_or_else(|| "DynamoDB insert requires a key".to_string())? so the failure becomes a recoverable error
  4. Add a regression test feeding a keyless Insert statement to execute_statement and asserting a clean error

Example fix

// before
let key = serde_json::to_string(statement.key.as_ref().expect("validated DynamoDB insert key"))
    .map_err(|error| error.to_string())?;
// after
let key_src = statement.key.as_ref()
    .ok_or_else(|| "DynamoDB insert statement requires a key".to_string())?;
let key = serde_json::to_string(key_src).map_err(|error| error.to_string())?;
Defensive patterns

Strategy: validation

Validate before calling

if let Some(stmt) = statement.as_dynamodb_mut() {
    if stmt.operation == DynamoDbStatementOperation::Insert && stmt.key.is_none() {
        return Err("DynamoDB insert statement requires a key".into());
    }
}

Type guard

fn has_dynamodb_key(stmt: &Statement) -> bool {
    stmt.key.is_some()
}

Try / catch

match driver.execute_statement(statement).await {
    Ok(result) => result,
    Err(e) => eprintln!("statement execution failed: {e}"),
    // panics are not catchable in normal flow — validate first
}

Prevention

When it happens

Trigger: Calling execute_statement with a DynamoDbStatementOperation::Insert whose `key` field is None — e.g. a hand-constructed Statement that bypasses parse_dynamodb_statement, or a code path that forgets to validate key presence for inserts (see rejects_write_statement_without_explicit_key).

Common situations: Building Statement structs programmatically instead of via the statement parser; a validation refactor dropping the insert-key check; deserializing statements from external input (JSON/API) without re-running validation.

Related errors


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