BoundaryML/baml · error · ConvertError

Float literals cannot be parsed

Error message

Float literals cannot be parsed

What it means

`ConvertError::FloatLiteral` is thrown when the sap_model converter encounters a float literal in a position where floats cannot be represented — the target type model only supports integer literals, so any float literal is rejected outright.

Source

Thrown at baml_language/crates/bex_sap/src/sap_model/convert.rs:28

use ::sys_types::{ClassDefinition, DefKey, EnumDefinition, SapTy};
use indexmap::IndexMap;

use crate::sap_model::{
    self, AnnotatedEnumVariant, AnnotatedField, AnnotatedTy, ArrayTy, AttrLiteral, BigintLiteralTy,
    BigintTy, BoolLiteralTy, BoolTy, ClassTy, EnumTy, EnumVariantTy, FloatTy, IntLiteralTy, IntTy,
    MapTy, MediaTy, NullTy, StringLiteralTy, StringTy, TyResolved, TyWithMeta, TypeAnnotations,
    TypeRefDb, UnionTy,
};

impl crate::sap_model::TypeIdent for DefKey {}

#[derive(thiserror::Error, Debug)]
pub enum ConvertError {
    #[error("Failed to parse float: {0}")]
    ParseFloat(#[from] std::num::ParseFloatError),
    #[error("Unknown media kind")]
    UnknownMediaKind,
    #[error("Float literals cannot be parsed")]
    FloatLiteral,
    #[error("Non-parsable type: {0:?}")]
    NonParsableType(Box<SapTy>),
    #[error("Unknown class: {0}")]
    UnknownClass(DefKey),
    #[error("Unknown enum: {0}")]
    UnknownEnum(DefKey),
    #[error("Unknown type alias: {0}")]
    UnknownTypeAlias(DefKey),
    #[error("Unknown name (could not determine if it was a class, enum, or type alias): {0}")]
    UnknownName(DefKey),
    #[error("Could not add a type to the database as the name `{0}` is already present")]
    AlreadyPresent(DefKey),
    #[error("Recursion depth exceeded for {0}")]
    RecursionDepthExceeded(&'static str),
    #[error("Unions must be flattened")]
    UnflattenedUnion,
    /// Something like `type A = B; type B = A;` is invalid.

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Replace the float literal with an integer literal in the source (e.g. `1` instead of `1.5`).
  2. Check the language spec: float literal types are not supported; use a named float type or constraint instead.
  3. If you maintain the converter, emit a better diagnostic pointing at the offending literal.
  4. Use a range/validated string field instead of a literal type for non-integer values.

Example fix

// before (BLP source)
type Threshold = 1.5;
// after
type Threshold = 1; // integer literal types only
Defensive patterns

Strategy: validation

Validate before calling

fn is_float_literal(s: &str) -> bool {
    s.contains('.') || s.contains('e') || s.contains('E')
}
// reject float literals in integer-literal-type positions before conversion

Try / catch

match convert(ty) {
    Ok(m) => m,
    Err(ConvertError::FloatLiteral) => { eprintln!("float literal types unsupported at {ty:?}"); Err(MyErr::FloatLiteralType) }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Converting a type expression (e.g. a numeric literal used as a type parameter or enum-ish literal type) that contains a non-integer float such as `1.5`, where the target type system only admits integer literals.

Common situations: Writing `type X = 1.5` style literal types in BLP source; passing float-typed config values where integer literal types are expected; porting code from a system that allowed float literal types.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/5cb68c2e1224c287. Report an issue: GitHub.