diesel-rs/diesel · error · syn::Error
expect `SQL` as ABI
Error message
expect `SQL` as ABI
What it means
The `sql_function!` macro parses an `extern "SQL" { ... }` block. The ABI string of the foreign module must be exactly `"SQL"`; any other ABI (e.g. `"C"`, missing name, or a typo) is rejected in `parse` with this error.
Solutions
- Change the ABI to exactly `extern "SQL"`.
- If you omitted the ABI string, add `"SQL"` after `extern`.
- Check for case mistakes: it must be uppercase `SQL`.
Example fix
// before
sql_function! {
extern "C" {
fn lower(x: Text) -> Text;
}
}
// after
sql_function! {
extern "SQL" {
fn lower(x: Text) -> Text;
}
} Defensive patterns
Strategy: validation
Validate before calling
// Use the canonical template for sql_function blocks:
// sql_function! { extern "SQL" { fn name(args...) -> Ret; } } Prevention
- Always copy the `extern "SQL"` template from diesel docs, not from FFI examples.
- Remember ABI strings are case-sensitive: `SQL` not `sql` or `C`.
- Do not let IDE snippets auto-complete `extern "C"` inside sql_function macros.
When it happens
Trigger: Writing `extern "C" { ... }`, `extern { ... }`, or misspelled ABI (e.g. `extern "sql"`) inside a `sql_function!` invocation or a module using the `#[sql_function]` foreign-mod syntax.
Common situations: Copy-pasting a normal FFI extern block into `sql_function!`; IDE auto-completing `extern "C"`; case-sensitivity mistakes (`"sql"` vs `"SQL"`).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid variadic argument count: not enough function…
- cannot find argument corresponding to the generic
- expect `SQL` function blocks to be safe
- , the correct format is `#[aggregate]
- , the correct format is `#[skip_return_type_helper]
AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07).
Data as JSON: /api/errors/fa8916c55d7054a7.
Report an issue: GitHub.
Appendix: source
Thrown at diesel_derives/src/sql_function.rs:1177
impl Parse for ExternSqlBlock {
fn parse(input: ParseStream) -> Result<Self> {
let mut error = None::<syn::Error>;
let mut combine_error = |e: syn::Error| {
error = Some(
error
.take()
.map(|mut o| {
o.combine(e.clone());
o
})
.unwrap_or(e),
)
};
let block = syn::ItemForeignMod::parse(input)?;
if block.abi.name.as_ref().map(|n| n.value()) != Some("SQL".into()) {
return Err(syn::Error::new(block.abi.span(), "expect `SQL` as ABI"));
}
if let Some(unsafety) = block.unsafety {
return Err(syn::Error::new(
unsafety.span(),
"expect `SQL` function blocks to be safe",
));
}
let parsed_block_attrs = parse_attributes(&mut combine_error, block.attrs);
let item_count = block.items.len();
let function_decls_input = block
.items
.into_iter()
.map(|i| syn::parse2::<SqlFunctionDecl>(quote! { #i }));
let mut function_decls = Vec::with_capacity(item_count);
for decl in function_decls_input {View on GitHub (pinned to 6fa6ed01b2)