Skip to main content
Version: dev

Troubleshooting

This page covers common issues and debugging techniques for Apache Fory™ Rust.

Common Issues

Type Registry Errors

Error: TypeId ... not found in type_info registry

Cause: The type was never registered with the current Fory instance.

Solution: Register the type before serialization:

let mut fory = Fory::default();
fory.register::<MyStruct>(100)?; // Register before use

Confirm that:

  • Every concrete dynamic target is registered through the matching structural, union, or custom serializer API.
  • The same ID or name mapping is reused on the deserialize side.

For external-type serialization, register the selected external structural or custom serializer, not its third-party target:

fory.register::<UserSerializer>(100)?;

Do not register VecSerializer<UserSerializer> or another carrier serializer. Register UserSerializer, then use recursive list, map, or tuple annotations at fields, or select the carrier serializer at a root.

Type Mismatch Errors

Cause: Field types are incompatible or schema has changed.

Solution:

  • Keep compatible mode enabled for schema evolution
  • Ensure field types match across versions
// Remove any compatible(false) override from the peers.
let fory = Fory::builder()
// existing options
.build();

External-Type Serialization Selection Errors

If derive reports that with targets the wrong type, verify that the selected serializer declares the exact field target:

impl Serializer for UserSerializer {
type Target = third_party::User;
// ...
}

For a transparent holder, select the carrier serializer whose target is the exact field type:

#[fory(with = OptionSerializer<UserSerializer>)]
user: Option<third_party::User>

For an exact container field, a carrier serializer is also valid:

#[fory(with = VecSerializer<UserSerializer>)]
users: Vec<third_party::User>

Use recursive collection syntax when selecting an element, map child, or tuple position:

#[fory(list(element(with = UserSerializer)))]
users: Vec<third_party::User>

If registration fails only in xlang mode, check whether the external structural serializer contains a native Rust enum variant with multiple fields. That shape has no xlang UNION representation; use native mode or change the shared schema.

Debugging Techniques

Enable Panic on Error for Backtraces

Toggle FORY_PANIC_ON_ERROR=1 alongside RUST_BACKTRACE=1 to panic at the exact site an error is constructed:

RUST_BACKTRACE=1 FORY_PANIC_ON_ERROR=1 cargo test --features tests

Reset the variable afterwards to avoid aborting user-facing code paths.

Struct Field Tracing

Add the #[fory(debug)] attribute alongside #[derive(ForyStruct)] to emit hook invocations:

#[derive(ForyStruct)]
#[fory(debug)]
struct MyStruct {
field1: i32,
field2: String,
}

Once compiled with debug hooks, call these functions to plug in custom callbacks:

  • set_before_write_field_func
  • set_after_write_field_func
  • set_before_read_field_func
  • set_after_read_field_func

Use reset_struct_debug_hooks() when you want the defaults back.

Lightweight Logging

Without custom hooks, enable ENABLE_FORY_DEBUG_OUTPUT=1 to print field-level read/write events:

ENABLE_FORY_DEBUG_OUTPUT=1 cargo test --features tests

This is especially useful when investigating alignment or cursor mismatches.

Inspect Generated Code

Use cargo expand to inspect code generated by Fory derive macros:

cargo expand --test mod $mod$::$file$ > expanded.rs

Running Tests

Run All Tests

cargo test --features tests

Run Specific Test

cargo test -p tests --test $test_file $test_method

Run Test with Debugging

RUST_BACKTRACE=1 FORY_PANIC_ON_ERROR=1 ENABLE_FORY_DEBUG_OUTPUT=1 \
cargo test --test mod $dir$::$test_file::$test_method -- --nocapture

Test-Time Hygiene

Some integration tests expect FORY_PANIC_ON_ERROR to remain unset. Export it only for focused debugging sessions:

# For specific debugging only
FORY_PANIC_ON_ERROR=1 cargo test -p tests --test specific_test -- --nocapture

# Normal test run (without panic on error)
cargo test --features tests

Error Handling Best Practices

Prefer the static constructors on the facade Error type:

  • Error::type_mismatch
  • Error::invalid_data
  • Error::unknown

This keeps diagnostics consistent and makes opt-in panics work correctly.

Quick Reference

Environment VariablePurpose
RUST_BACKTRACE=1Enable stack traces
FORY_PANIC_ON_ERROR=1Panic at error site for debugging
ENABLE_FORY_DEBUG_OUTPUT=1Print field-level read/write events