Closest to action-at-a-distance I got in rust

Not asking for help, just telling a story about weirdest library interaction I've seen in rust so far.

Here I have smallest project:

[package]
name = "build-test"
version = "0.1.0"
edition = "2024"

[dependencies]
prometheus-http-query = "0.8.3"
tokio = { version = "1.46.1", features = ["full"] }

# used in other part of the code:
apache-avro = { version = "0.17.0", default-features = false, optional = false }
#[tokio::main]
async fn main() {
    let val = prometheus_http_query::query("http://localhost:9090", "vector(42)")
        .expect("failed to execute query")
        .get()
        .await
        .expect("getting query result");
    println!("{val:?}") // PromqlResult { data: Vector([InstantVector { metric: {}, sample: Sample { timestamp: 1752133523.607, value: 42.0 } }]), stats: None }
}

Now, if I update the avro version:

# ...

# used in other part of the code:
apache-avro = { version = "0.19.0", default-features = false, optional = false }

Same code fails with weird error:

thread 'main' panicked at src/main.rs:7:10:
getting query result: Client(ClientError { message: "failed to parse JSON response from server", source: Some(reqwest::Error { kind: Decode, source: Error("invalid type: map, expected f64", line: 0, column: 0) }) })

Fast-forward a full day of debugging (in a real project it took me a lot of time to find that avro is the culprit), turns out that in version 0.18.0 they turned on serde-json feature of bigdecimal lib (issue) which turns on arbitrary_precision feature of serde_json (issue) which, in turn, triggers long standing bug in serde_json (issue) which breaks parsing floating point numbers behind #[serde(flatten)] annotation if this feature is enabled.

What did we learn today? IDK, maybe the real arbitrary precision is the frends we found along the way? :grin:

4 Likes

It is the type of bug Rust should target to eliminate. I don't mean the specific bug but akin to it getting rid of all data races. I'm just not sure there is any practical way to make features not have ability to break what worked prior without though.

It is a lot like debug/release builds, they should be identical (except for extra assertions and run performance.) I have not read many commenting regarding such with Rust but in past with C/C++ it is often mentioned.

Note though that this was a semver-major update of apache-avro, as long as Rust/Cargo conventions are concerned, so from the end consumer POV, breaking changes are technically possible. This is not the case for apache-avro itself, of course, since adding a feature should never be breaking.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.