proto-attr Compile Error Showcase
Unknown Extension Attribute
Using an unknown ORM attribute like indexed produces a clear error
listing all available attributes (skip, rename, column).
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::indexed)] id: i64, } fn main() {}
Compiler Error
error: unknown attribute `indexed`; did you mean `index`?
--> src/main.rs:5:24
|
5 | #[faket(proto_ext::indexed)]
| ^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Typo in Attribute Name
Common typos like skp instead of skip are caught at compile time
with a helpful "did you mean?" suggestion.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::skp)] password_hash: String, } fn main() {}
Compiler Error
error: unknown attribute `skp`; did you mean `skip`?
--> src/main.rs:5:24
|
5 | #[faket(proto_ext::skp)]
| ^^^
error: could not compile test (bin "test") due to 1 previous error
Unit Attribute with Arguments
The skip attribute is a unit variant that takes no arguments.
Passing arguments produces a clear error explaining the correct usage.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::skip("serialization"))] password_hash: String, } fn main() {}
Compiler Error
error: `skip` does not take arguments; use just `skip`
--> src/main.rs:5:24
|
5 | #[faket(proto_ext::skip("serialization"))]
| ^^^^
error: could not compile test (bin "test") due to 1 previous error
Newtype Attribute Missing Value
The rename attribute requires a string value to specify the new name.
Omitting the value produces an error showing the expected syntax.
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(proto_ext::rename)] struct UserProfile { email: String, } fn main() {}
Compiler Error
error: `rename` requires a string value: `rename("name")` or `rename = "name"`
--> src/main.rs:4:20
|
4 | #[faket(proto_ext::rename)]
| ^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Unknown Field in Struct Attribute
Typos in field names like nam instead of name are caught
with a "did you mean?" suggestion and list of valid fields
(name, nullable, sql_type, primary_key, auto_increment).
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::column(nam = "user_id", primary_key))] id: i64, } fn main() {}
Compiler Error
error: unknown field `nam`; did you mean `name`? Known fields: name, nullable, sql_type, primary_key, auto_increment
--> src/main.rs:5:31
|
5 | #[faket(proto_ext::column(nam = "user_id", primary_key))]
| ^^^
error: could not compile test (bin "test") due to 1 previous error
Struct Field Missing Value
The name field in column requires a string value.
Using it as a flag produces an error showing the correct syntax.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::column(name, primary_key))] id: i64, } fn main() {}
Compiler Error
error: `name` requires a string value: `name = "value"`
= help: Override the database column name; use `name = "col_name"` (defaults to Rust field name)
--> src/main.rs:5:31
|
5 | #[faket(proto_ext::column(name, primary_key))]
| ^^^^
error: could not compile test (bin "test") due to 1 previous error
Index Field Typo (list_string)
Typos in field names like column instead of columns are caught
with a helpful "did you mean?" suggestion.
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(proto_ext::index(column = ["id", "email"]))] struct UserIndex { id: i64, email: String, } fn main() {}
Compiler Error
error: unknown field `column`; did you mean `columns`? Known fields: name, columns, unique
--> src/main.rs:4:26
|
4 | #[faket(proto_ext::index(column = ["id", "email"]))]
| ^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Index Wrong Type for List
The columns field expects a list like ["a", "b"], not a string.
Using the wrong type produces a clear error explaining the expected format.
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(proto_ext::index(columns = "email"))] struct UserIndex { id: i64, email: String, } fn main() {}
Compiler Error
error: `columns` expects a list, not a single string; try `columns = ["email"]`
= help: Columns in this index; use `columns = ["col1", "col2"]` (order matters for query optimization)
--> src/main.rs:4:36
|
4 | #[faket(proto_ext::index(columns = "email"))]
| ^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Range Wrong Type for Integer
The min and max fields in range expect integers, not strings.
Using a string produces an error showing the correct syntax.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::range(min = "zero", max = 100))] age: i32, } fn main() {}
Compiler Error
error: `min` expected integer literal, got `"zero"`
--> src/main.rs:5:36
|
5 | #[faket(proto_ext::range(min = "zero", max = 100))]
| ^^^^^^
error: could not compile test (bin "test") due to 1 previous error
OnDelete String Instead of Identifier
The action field expects a bare identifier like cascade, not a string.
The error message suggests removing the quotes: action = cascade.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct Post { #[faket(proto_ext::on_delete(action = "cascade"))] author_id: i64, } fn main() {}
Compiler Error
error: `action` expects a bare identifier, not a string; try `action = cascade` (without quotes)
= help: What happens when referenced row is deleted; use `action = cascade` (delete), `set_null`, `restrict` (prevent), or `no_action`
--> src/main.rs:5:43
|
5 | #[faket(proto_ext::on_delete(action = "cascade"))]
| ^^^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Duplicate Field
Specifying the same field twice in an attribute is an error.
Each field can only appear once in an attribute.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::column(name = "user_id", name = "id"))] id: i64, } fn main() {}
Compiler Error
error: duplicate field `name`; each field can only be specified once
--> src/main.rs:5:49
|
5 | #[faket(proto_ext::column(name = "user_id", name = "id"))]
| ^^^^
error: could not compile test (bin "test") due to 1 previous error
Mixed Types in List
List fields require all elements to be the same type.
A string list like columns cannot contain integers.
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(proto_ext::index(columns = ["email", 123]))] struct UserIndex { id: i64, email: String, } fn main() {}
Compiler Error
error: expected string literal in list, got `123`
--> src/main.rs:4:46
|
4 | #[faket(proto_ext::index(columns = ["email", 123]))]
| ^^^
error: could not compile test (bin "test") due to 1 previous error
Wrong Bracket Type for List
Lists use square brackets [...], not curly braces {...}.
The error specifically tells you to use square brackets.
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(proto_ext::index(columns = {"email"}))] struct UserIndex { id: i64, email: String, } fn main() {}
Compiler Error
error: `columns` expects square brackets `[]`, not curly braces `{}`; try `columns = ["a", "b"]`
= help: Columns in this index; use `columns = ["col1", "col2"]` (order matters for query optimization)
--> src/main.rs:4:36
|
4 | #[faket(proto_ext::index(columns = {"email"}))]
| ^^^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Integer Overflow
The error shows the field name, the value, and the schema-defined type.
Each integer field in the grammar specifies its type (here: i64).
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::range(min = 99999999999999999999999))] score: i32, } fn main() {}
Compiler Error
error: `min` value `99999999999999999999999` is too large; this field accepts i64 (range -9223372036854775808 to 9223372036854775807)
--> src/main.rs:5:36
|
5 | #[faket(proto_ext::range(min = 99999999999999999999999))]
| ^^^^^^^^^^^^^^^^^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Bool Field with String Value
Boolean fields expect true or false literals, not strings.
The error suggests removing the quotes: primary_key = true.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::column(primary_key = "true"))] id: i64, } fn main() {}
Compiler Error
error: `primary_key` expects `true` or `false`, not a string; try `primary_key = true` (without quotes)
= help: Mark as primary key; use `primary_key` or `primary_key = true` (tables typically have one primary key)
--> src/main.rs:5:45
|
5 | #[faket(proto_ext::column(primary_key = "true"))]
| ^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Integer Field Used as Flag
Integer fields require a value; they cannot be used as flags.
Using min without = value produces an error.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::range(min, max = 100))] age: i32, } fn main() {}
Compiler Error
error: `min` requires an integer value: `min = 42`
= help: Minimum allowed value (inclusive); use `min = 0` to reject negative numbers
--> src/main.rs:5:30
|
5 | #[faket(proto_ext::range(min, max = 100))]
| ^^^
error: could not compile test (bin "test") due to 1 previous error
Identifier Instead of String
String fields require quoted values, not bare identifiers.
The error suggests adding quotes: name = "user_id".
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::column(name = user_id))] id: i64, } fn main() {}
Compiler Error
error: `name` expects a string literal, not an identifier; try `name = "user_id"` (with quotes)
= help: Override the database column name; use `name = "col_name"` (defaults to Rust field name)
--> src/main.rs:5:38
|
5 | #[faket(proto_ext::column(name = user_id))]
| ^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Single String Instead of List
List fields require [...] syntax even for a single element.
The error suggests wrapping in brackets: columns = ["email"].
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(proto_ext::index(columns = "email"))] struct UserIndex { id: i64, email: String, } fn main() {}
Compiler Error
error: `columns` expects a list, not a single string; try `columns = ["email"]`
= help: Columns in this index; use `columns = ["col1", "col2"]` (order matters for query optimization)
--> src/main.rs:4:36
|
4 | #[faket(proto_ext::index(columns = "email"))]
| ^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Help Text: Column Primary Key
Error messages include contextual help explaining the field AND how to use it.
The help shows: correct syntax, typical usage, and semantic meaning.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::column(primary_key = "yes"))] id: i64, } fn main() {}
Compiler Error
error: `primary_key` expects `true` or `false`, not a string; try `primary_key = true` (without quotes)
= help: Mark as primary key; use `primary_key` or `primary_key = true` (tables typically have one primary key)
--> src/main.rs:5:45
|
5 | #[faket(proto_ext::column(primary_key = "yes"))]
| ^^^^^
error: could not compile test (bin "test") due to 1 previous error
Help Text: Index Columns
The help text explains that columns specifies which columns
to include in the index: "Columns to include in the index".
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(proto_ext::index(columns))] struct UserIndex { id: i64, email: String, } fn main() {}
Compiler Error
error: `columns` requires a list value: `columns = ["a", "b"]`
= help: Columns in this index; use `columns = ["col1", "col2"]` (order matters for query optimization)
--> src/main.rs:4:26
|
4 | #[faket(proto_ext::index(columns))]
| ^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Help Text: Range Min
The help text clarifies that min is the "Minimum value (inclusive)".
Doc comments in the grammar DSL become contextual help in errors.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct User { #[faket(proto_ext::range(min = "zero"))] age: i32, } fn main() {}
Compiler Error
error: `min` expected integer literal, got `"zero"`
--> src/main.rs:5:36
|
5 | #[faket(proto_ext::range(min = "zero"))]
| ^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Valid Usage
When ORM attributes are used correctly, everything compiles smoothly.
This shows realistic usage patterns:
• skip - exclude structs/fields from generation
• rename - map to different table/column names
• column - full control: name, nullable, sql_type, primary_key, auto_increment
• index - database indexes with columns list (list_string field type)
• range - validation bounds with min/max (opt_i64 field type)
• on_delete - foreign key behavior with bare identifiers (ident field type)
Rust Input
use proto_attr::Faket; /// A table we want to exclude from ORM generation #[derive(Faket)] #[faket(proto_ext::skip)] struct InternalCache { data: Vec<u8>, } /// Map to a different table name #[derive(Faket)] #[faket(proto_ext::rename("user_profiles"))] struct UserProfile { email: String, } /// Full ORM column configuration example #[derive(Faket)] #[faket(proto_ext::index(name = "idx_user_email", columns = ["email"], unique))] struct User { /// Primary key with auto-increment #[faket(proto_ext::column(name = "id", primary_key, auto_increment))] id: i64, /// Custom column name #[faket(proto_ext::column(name = "user_name"))] name: String, /// Nullable TEXT field for bio #[faket(proto_ext::column(nullable, sql_type = "TEXT"))] bio: Option<String>, /// Non-nullable timestamp #[faket(proto_ext::column(nullable = false, sql_type = "TIMESTAMP"))] created_at: i64, /// Skip sensitive field from serialization #[faket(proto_ext::skip)] password_hash: String, /// Rename field for API compatibility #[faket(proto_ext::rename("email_address"))] email: String, /// Validation: age must be between 0 and 150 #[faket(proto_ext::range(min = 0, max = 150, message = "Age must be realistic"))] age: i32, } /// Foreign key with ON DELETE behavior #[derive(Faket)] struct Post { #[faket(proto_ext::column(primary_key, auto_increment))] id: i64, /// When author is deleted, cascade delete their posts #[faket(proto_ext::on_delete(action = cascade))] author_id: i64, /// When category is deleted, set to null #[faket(proto_ext::on_delete(action = set_null))] category_id: Option<i64>, title: String, } /// Composite index example #[derive(Faket)] #[faket(proto_ext::index(columns = ["user_id", "created_at"]))] #[faket(proto_ext::index(name = "idx_status", columns = ["status"], unique))] struct Order { #[faket(proto_ext::column(primary_key))] id: i64, user_id: i64, status: String, created_at: i64, } fn main() { println!("Compiles successfully!"); }
Compiler Error
✓ Compilation successful! No errors.
Top-Level: Basic Attributes
Top-level facet attributes like transparent, untagged, and rename_all
work without a namespace prefix.
Rust Input
use proto_attr::Faket; /// A newtype wrapper (transparent) #[derive(Faket)] #[faket(transparent)] struct UserId(i64); /// An untagged enum #[derive(Faket)] #[faket(untagged)] enum Message { Text(String), Number(i64), } /// Struct with rename_all for field case conversion #[derive(Faket)] #[faket(rename_all = "kebab-case")] struct Config { api_key: String, max_retries: i32, } fn main() {}
Compiler Error
✓ Compilation successful! No errors.
Top-Level: Multiple Attrs Combined
Multiple top-level attributes can be combined in a single #[faket(...)].
Commas separate distinct attributes, respecting balanced parentheses.
Rust Input
use proto_attr::Faket; /// Tagged enum with custom tag and content field names #[derive(Faket)] #[faket(tag = "type", content = "payload")] enum Event { Click { x: i32, y: i32 }, KeyPress(String), } /// Struct with multiple top-level attrs #[derive(Faket)] #[faket(deny_unknown_fields, default, rename_all = "camelCase")] struct ApiRequest { user_id: i64, request_type: String, } fn main() {}
Compiler Error
✓ Compilation successful! No errors.
Top-Level: Mixed with Namespaced
Top-level facet attributes and namespaced extension attributes can be
freely mixed in the same #[faket(...)] or on different lines.
Rust Input
use proto_attr::Faket; /// Mix top-level facet attrs with extension attrs on a struct #[derive(Faket)] #[faket(rename_all = "snake_case", proto_ext::index(columns = ["id", "name"]))] struct User { #[faket(proto_ext::column(primary_key, auto_increment))] id: i64, #[faket(default, proto_ext::column(name = "user_name"))] name: String, #[faket(proto_ext::skip, proto_ext::rename("ignored"))] internal_cache: Vec<u8>, } fn main() {}
Compiler Error
✓ Compilation successful! No errors.
Top-Level: Field-Level Attrs
Top-level attributes like default and untagged can also be used
at the field level, mixed with extension attributes.
Rust Input
use proto_attr::Faket; #[derive(Faket)] struct Settings { /// Field uses default if missing #[faket(default)] timeout_ms: i64, /// Multiple field attrs: default + extension #[faket(default, proto_ext::range(min = 1, max = 100))] max_retries: i32, /// Combining untagged with column config (field-level) #[faket(untagged, proto_ext::column(nullable))] optional_data: Option<String>, } fn main() {}
Compiler Error
✓ Compilation successful! No errors.
Top-Level: Complex Real-World Example
A complete real-world example combining:
• Struct-level: deny_unknown_fields, rename_all, index
• Field-level: default, column, range, skip, rename, on_delete
• Enum: tag, content, rename_all
Rust Input
use proto_attr::Faket; /// A complete API model with all attribute types #[derive(Faket)] #[faket(deny_unknown_fields, rename_all = "camelCase")] #[faket(proto_ext::index(name = "idx_api_model", columns = ["id", "created_at"], unique))] struct ApiModel { #[faket(proto_ext::column(primary_key, auto_increment, name = "model_id"))] id: i64, #[faket(default, proto_ext::column(sql_type = "TIMESTAMP"))] created_at: i64, #[faket(proto_ext::rename("modelName"), proto_ext::column(name = "name"))] model_name: String, #[faket(default, proto_ext::range(min = 0, max = 1000000))] score: i64, #[faket(proto_ext::skip)] internal_state: Vec<u8>, #[faket(proto_ext::on_delete(action = cascade))] parent_id: Option<i64>, } /// Enum with adjacently tagged representation #[derive(Faket)] #[faket(tag = "kind", content = "data", rename_all = "SCREAMING_SNAKE_CASE")] enum ApiResponse { Success { value: i64 }, Error { code: i32, message: String }, Pending, } fn main() {}
Compiler Error
✓ Compilation successful! No errors.
Top-Level: Unknown Attribute Error
Using an unknown top-level attribute produces a helpful error
with suggestions for valid attributes.
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(unknown_attr)] struct Bad { field: i32, } fn main() {}
Compiler Error
error: unknown attribute `unknown_attr`; expected one of: transparent, untagged, rename_all, tag, content, deny_unknown_fields, default, skip, rename, column, index, range, on_delete
--> src/main.rs:4:9
|
4 | #[faket(unknown_attr)]
| ^^^^^^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Top-Level: Wrong Syntax Error
Top-level unit attributes like transparent don't take arguments.
The error message explains the correct usage.
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(transparent("value"))] struct Bad(i64); fn main() {}
Compiler Error
error: `transparent` does not take arguments; use just `transparent`
--> src/main.rs:4:9
|
4 | #[faket(transparent("value"))]
| ^^^^^^^^^^^
error: could not compile test (bin "test") due to 1 previous error
Top-Level: Missing Value Error
Newtype attributes like rename_all require a value.
Omitting it produces a clear error.
Rust Input
use proto_attr::Faket; #[derive(Faket)] #[faket(rename_all)] struct Bad { field: i32, } fn main() {}
Compiler Error
error: `rename_all` requires a string value: `rename_all("name")` or `rename_all = "name"`
--> src/main.rs:4:9
|
4 | #[faket(rename_all)]
| ^^^^^^^^^^
error: could not compile test (bin "test") due to 1 previous error