{"record":{"id":"254023101d84a2f1","repo":"t8y2/dbx","slug":"validated-dynamodb-put-key","errorCode":null,"errorMessage":"validated DynamoDB put key","messagePattern":"validated DynamoDB put key","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbx-core/src/db/dynamodb_driver.rs","lineNumber":380,"sourceCode":"                &statement.table,\n                effective_limit,\n                filter.as_deref(),\n                sort.as_deref(),\n                statement.cursor.as_deref(),\n            )\n            .await?;\n            Ok(document_query_result(result, started))\n        }\n        DynamoDbStatementOperation::Insert => {\n            let key = serde_json::to_string(statement.key.as_ref().expect(\"validated DynamoDB insert key\"))\n                .map_err(|error| error.to_string())?;\n            let item = serde_json::to_string(statement.item.as_ref().expect(\"validated DynamoDB insert item\"))\n                .map_err(|error| error.to_string())?;\n            insert_item_with_expected_identity(client, &statement.table, &item, Some(&key)).await?;\n            Ok(affected_query_result(1, started))\n        }\n        DynamoDbStatementOperation::Put => {\n            let key = serde_json::to_string(statement.key.as_ref().expect(\"validated DynamoDB put key\"))\n                .map_err(|error| error.to_string())?;\n            let item = serde_json::to_string(statement.item.as_ref().expect(\"validated DynamoDB put item\"))\n                .map_err(|error| error.to_string())?;\n            let affected = update_item(client, &statement.table, &key, &item).await?;\n            Ok(affected_query_result(affected, started))\n        }\n        DynamoDbStatementOperation::Delete => {\n            let key = serde_json::to_string(statement.key.as_ref().expect(\"validated DynamoDB delete key\"))\n                .map_err(|error| error.to_string())?;\n            let affected = delete_item(client, &statement.table, &key).await?;\n            Ok(affected_query_result(affected, started))\n        }\n    }\n}\n\nfn parse_dynamodb_statement(source: &str) -> Result<DynamoDbStatement, String> {\n    let mut lines = source.lines();\n    let header = lines","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/crates/dbx-core/src/db/dynamodb_driver.rs#L362-L398","documentation":"Panic from `Option::expect` on `statement.key` for a DynamoDB Put (upsert) statement. Put, like Insert, requires an explicit key that validation is supposed to guarantee; a None key reaching this line means validation was bypassed and the process panics. It is an internal contract violation, not a DynamoDB service error.","triggerScenarios":"Calling execute_statement with DynamoDbStatementOperation::Put and key = None — e.g. statements built in code, loaded from external JSON, or a code path where the put-key validation was skipped (rejects_write_statement_without_explicit_key not run).","commonSituations":"Programmatic statement construction; bypassing the parser when proxying user statements; test fixtures missing keys; regression after refactoring statement validation.","solutions":["Construct Put statements only via parse_dynamodb_statement, which enforces explicit keys for writes","Check statement.key.is_some() before invoking execute_statement for Put","Replace expect with ok_or_else to surface a recoverable 'put requires a key' error","Cover keyless Put in unit tests to lock in the validation"],"exampleFix":"// before\nlet key = serde_json::to_string(statement.key.as_ref().expect(\"validated DynamoDB put key\"))\n    .map_err(|error| error.to_string())?;\n// after\nlet key_src = statement.key.as_ref()\n    .ok_or_else(|| \"DynamoDB put statement requires a key\".to_string())?;\nlet key = serde_json::to_string(key_src).map_err(|error| error.to_string())?;","handlingStrategy":"validation","validationCode":"if stmt.operation == DynamoDbStatementOperation::Put && stmt.key.is_none() {\n    return Err(\"DynamoDB put statement requires a key\".into());\n}","typeGuard":"fn has_explicit_key(stmt: &Statement) -> bool {\n    matches!(stmt.operation, DynamoDbStatementOperation::Insert | DynamoDbStatementOperation::Put | DynamoDbStatementOperation::Delete)\n        .implies(stmt.key.is_some())\n}","tryCatchPattern":"driver.execute_statement(stmt).await.unwrap_or_else(|e| { eprintln!(\"put failed: {e}\"); fallback_result() })","preventionTips":["Enforce explicit keys for all write operations at construction time","Reuse the parser's validation test (rejects_write_statement_without_explicit_key) in your own suite","Validate key presence before batching statements"],"tags":["rust","dynamodb","panic","invariant-violation"],"backgroundTag":"internal-invariant-panic","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}