{"record":{"id":"33af3104abebeb9e","repo":"nautechsystems/nautilus_trader","slug":"failed-to-write-token-data-e","errorCode":null,"errorMessage":"Failed to write token data: {e}","messagePattern":"Failed to write token data: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/copy.rs","lineNumber":805,"sourceCode":"        row_data.write_all(&(address_bytes.len() as i32).to_be_bytes())?;\n        row_data.write_all(&address_bytes)?;\n\n        let name_bytes = token.name.as_bytes();\n        row_data.write_all(&(name_bytes.len() as i32).to_be_bytes())?;\n        row_data.write_all(name_bytes)?;\n\n        let symbol_bytes = token.symbol.as_bytes();\n        row_data.write_all(&(symbol_bytes.len() as i32).to_be_bytes())?;\n        row_data.write_all(symbol_bytes)?;\n\n        let decimals_bytes = (i32::from(token.decimals)).to_be_bytes();\n        row_data.write_all(&(decimals_bytes.len() as i32).to_be_bytes())?;\n        row_data.write_all(&decimals_bytes)?;\n\n        copy_in\n            .send(row_data)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to write token data: {e}\"))?;\n        Ok(())\n    }\n\n    /// Writes a single pool in PostgreSQL binary format.\n    ///\n    /// Each row in binary format consists of:\n    /// - 2-byte field count\n    /// - For each field: 4-byte length followed by data (or -1 for NULL)\n    async fn write_pool_binary(\n        &self,\n        copy_in: &mut sqlx::postgres::PgCopyIn<sqlx::pool::PoolConnection<sqlx::Postgres>>,\n        chain_id: u32,\n        pool: &Pool,\n    ) -> anyhow::Result<()> {\n        use std::io::Write;\n        let mut row_data = Vec::new();\n\n        row_data.write_all(&14u16.to_be_bytes())?;","sourceCodeStart":787,"sourceCodeEnd":823,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/copy.rs#L787-L823","documentation":"write_token_binary serializes one token row (including decimals with its byte-length prefix) and sends it to the server via the COPY binary sink. This error wraps the send failure. Tokens are copied via copy_tokens, so any sink error surfaces here per row.","triggerScenarios":"copy_in.send(row_data) fails during copy_tokens — connection drop, server-side COPY abort, or bytes not matching the token table's expected binary layout (e.g. wrong decimals length prefix).","commonSituations":"Schema migration changed column order/types for tokens; connection pool closed mid-sync; proxy/firewall severing long-running COPY connections.","solutions":["Read the wrapped {e} to determine connection vs data cause","Verify token table schema matches the binary encoding (address, symbol, name, decimals order and types)","Reconnect/retry copy_tokens after transient network failures","Ensure partitions for the chain's token table exist before copying"],"exampleFix":"// before: assumes connection is always alive across a long copy\ndb.copy_tokens(chain, &tokens).await?;\n// after: retry with backoff on transient failure\nfor attempt in 0..3 {\n    match db.copy_tokens(chain, &tokens).await {\n        Ok(()) => break,\n        Err(e) if attempt < 2 && is_transient(&e) => tokio::time::sleep(backoff(attempt)).await,\n        Err(e) => return Err(e),\n    }\n}","handlingStrategy":"retry","validationCode":"// confirm token table shape before copy\nlet cols: Vec<(String,)> = sqlx::query_as(\n    \"SELECT column_name FROM information_schema.columns WHERE table_name='token' ORDER BY ordinal_position\"\n).fetch_all(&pool).await?;\nassert_eq!(cols.len(), EXPECTED_TOKEN_COLUMNS, \"token schema drift\");","typeGuard":null,"tryCatchPattern":"match db.copy_tokens(chain, &tokens).await {\n    Err(e) if is_transient(&e) => {\n        tokio::time::sleep(RETRY_DELAY).await;\n        db.copy_tokens(chain, &tokens).await?;\n    }\n    other => other?,\n}","preventionTips":["Run migrations before syncing so the token table matches the binary encoder","Ensure chain partitions exist before copy_tokens","Handle token fields that may be NULL (symbol/name) consistently with the encoder","Monitor connection health; abort early rather than streaming into a dead connection"],"tags":["database","postgres","copy","binary-format"],"backgroundTag":"database-write-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}