Skip to content

feat: expose duckdb_result_error_type() to populate ErrorCode in DuckDBFailure#752

Open
EdanStasiuk wants to merge 4 commits intoduckdb:mainfrom
EdanStasiuk:fix/error-code-from-result-type
Open

feat: expose duckdb_result_error_type() to populate ErrorCode in DuckDBFailure#752
EdanStasiuk wants to merge 4 commits intoduckdb:mainfrom
EdanStasiuk:fix/error-code-from-result-type

Conversation

@EdanStasiuk
Copy link
Copy Markdown

@EdanStasiuk EdanStasiuk commented Apr 30, 2026

Summary

Fixes #679. Currently every DuckDBFailure error carries ErrorCode::Unknown regardless of what actually went wrong. This is because duckdb-rs only reads a generic success/failure integer from the C API and never calls duckdb_result_error_type(), which has been available since DuckDB v0.10 and returns the actual error type.

This PR adds ErrorCode::Http and a full mapping from all duckdb_error_type C constants to Rust ErrorCode variants, then calls duckdb_result_error_type() when constructing DuckDBFailure errors from a duckdb_result. This allows users to match on specific error codes instead of parsing error message strings, which is fragile and breaks between DuckDB versions.

After this change, errors from execute_streaming and execute_extracted_statement will carry the correct code. For example, ErrorCode::Http for HTTP fetch failures, ErrorCode::ConstraintViolation for constrain violations, and ErrorCode::NotFound for missing tables.

Tests

All test cases pass except for types::test::test_dynamic_type, which is already failing on the main branch.

@EdanStasiuk
Copy link
Copy Markdown
Author

EdanStasiuk commented May 1, 2026

As this PR currently stands, all relevant unit tests are passing except for test::test_interrupt, which is caused by my re-executing via duckdb_execute_prepared after duckdb_execute_prepared_arrow fails inside execute(). When a query is interrupted the connection is in a bad state and the second execution hangs.

The way I see it, there's 3 way to address this:

  1. Check the arrow error message before re-executing, and if it contains "INTERRUPT" skip the re-execution and return immediately. This fixes the test but is fragile since it's string matching on error messages, which is exactly what this PR is trying to move away from.
  2. Leave the arrow path untouched and revert test_notnull_constraint_error back to asserting ErrorCode::Unknown. Typed errors would still work for execute_streaming and execute_extracted_statement, which covers the HTTP error case from the original issue.
  3. Migrate execute() off duckdb_execute_prepared_arrow entirely and onto duckdb_execute_prepared. This would give typed errors without any re-execution hack, and also addresses the fact that duckdb_execute_prepared_arrow is marked as deprecated in the C API. However this requires replacing all the data reading code in RawStatement that currently depends on the duckdb_arrow handle, which looks to be a significant rewrite and out of scope for this PR.

Happy to go in whichever direction the maintainers prefer.

@EdanStasiuk EdanStasiuk marked this pull request as ready for review May 4, 2026 00:48
@EdanStasiuk EdanStasiuk changed the title DRAFT feat: expose duckdb_result_error_type() to populate ErrorCode in DuckDBFailure feat: expose duckdb_result_error_type() to populate ErrorCode in DuckDBFailure May 4, 2026
@EdanStasiuk
Copy link
Copy Markdown
Author

Un-drafting the PR with option 2, as described previously. Happy to make any changes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detecting HTTP 404 (Not Found) responses

1 participant